Use Dataset created from 02_CLS_Data_Summary_2022_0914_Data_Analysis File

Loading Data

Load Google Sheet

Final_CLS_2022_Study_List_Non_Search_model_file <- read_sheet(
  "https://docs.google.com/spreadsheets/d/1N48rTeq7md0v8w8pG_8XIiuapPHQAeO5WoWIB3eaceI/edit#gid=1449351377",
  sheet = "FinalDataset_2022_Update"
) %>%
  mutate(
    Significant_Spend =
      as.numeric(
        case_when(
          probability_of_lift >= 0.9 ~ 1,
          TRUE ~ 0
        )
      ),
    country = case_when(
      country == "NA" ~ "US",
      TRUE ~ country
    ),
    region_v2 = case_when(
      country == "US" ~ "NA",
      country == "CA" ~ "NA",
      country == "US + CA" ~ "NA",
      TRUE ~ region
    )
  ) %>%
  filter(channel != "Search") %>%
  # filter out studies without reported lifts
  filter(exposed != -1) %>%
  # filter out google pay study
  filter(study_id != "149142217") %>%
  # filter out very negative absolute lifts
  filter(absolute_lift > -1000) %>%
  mutate(
    pa = case_when(
      pa == "Google Ads" ~ "SMB", # Step 1
      pa == "YouTube" & conversion != "Type 256522942 ([MCC] YouTube TV - Web - Trial Start)" ~ "YTMP", # Step 2
      pa == "YouTube Premium" ~ "YTMP", # Step 2
      conversion == "Type 256522942 ([MCC] YouTube TV - Web - Trial Start)" ~ "YouTube TV", # Step 2
      pa == "Cloud" & conversion != "Type 14257803 (Enterprise - Apps - Signup Confirm - Unique)" ~ "Cloud Workspace", # Step 3
      pa == "Cloud" & conversion == "Type 14257803 (Enterprise - Apps - Signup Confirm - Unique)" ~ "Cloud GCP", # Step 3
      pa == "Project Fi" ~ "Google Fi", # Step 4
      pa == "Google Chrome" ~ "Chrome",
      TRUE ~ pa
    )
  ) %>%
  mutate(
    parsed_type = parse_number(conversion),
    grouped_conversion = case_when(
      conversion %in% c("Chromebook Microsite Referral Clicks Q4 2015", "Type 251422729 (Chromebooks Microsite Referral Clicks (Q4 2017))") ~ "Chromebook Referrals",
      conversion %in% c("Desktop Downloads", "Type 11541547 (Desktop Download)") ~
        "Desktop Downloads",
      pa == "Pixel" ~ "Mobile Conversions",
      pa == "DSM" ~ "Non-Mobile Device Conversions",
      conversion == "Type 302982954 (Lena - P Lead)" ~ "Lena P Lead",
      conversion == "Type 288347008 (LENA - B Lead)" ~ "Lena B Lead",
      conversion == "Type 288697653 (LENA - Q Lead)" ~ "Lena Q Lead",
      parsed_type %in% c(181283993, 855508686) ~ "Workspace Free Trial Start",
      parsed_type == 330755641 ~ "Microsite Conversions",
      parsed_type == 14257803 ~ "Enterprise Signups",
      parsed_type == 289680712 ~ "Google(iOs) First Open",
      parsed_type == 256522942 ~ "YouTube TV - Web - Trial Start",
      parsed_type %in% c(452391534, 221497833, 277150074) ~ "Trial Signups Complete",
      TRUE ~ conversion
    ),
    pa = case_when(
      conversion == "Type 288697653 (LENA - Q Lead)" ~ "SMB-QLead",
      TRUE ~ pa
    )
  ) %>%
  filter(absolute_lift > 0)


# all.equal(Final_CLS_2022_Study_List_Non_Search_model_file,Final_CLS_2022_Study_List_Non_Search_v3)

Create All Response Curves only normal powers

Folder for all Output and scripts

file.sources <- list.files(path = "RScripts/", pattern = "*.R", full.names = TRUE)
sapply(file.sources, source, .GlobalEnv)
        RScripts/best_ind_function.R RScripts/export_rplots_function.R RScripts/export_rplots_function2.R
value   ?                            ?                                 ?                                 
visible FALSE                        FALSE                             FALSE                             
        RScripts/graphing_function.R RScripts/graphing_function_elasticnet.R RScripts/graphing_function_rlm.R
value   ?                            ?                                       ?                               
visible FALSE                        FALSE                                   FALSE                           
        RScripts/graphing_function2.R RScripts/graphing_function3.R RScripts/graphing_function4.R
value   ?                             ?                             ?                            
visible FALSE                         FALSE                         FALSE                        
        RScripts/graphing_function4_w_anom.R RScripts/model_wrapper_function.R RScripts/model_wrapper_function2.R
value   ?                                    ?                                 ?                                 
visible FALSE                                FALSE                             FALSE                             
        RScripts/named_group_split.R RScripts/names_function.R RScripts/ridge_lasso_function.R RScripts/ridge_lasso_function2.R
value   ?                            ?                         ?                               ?                               
visible FALSE                        FALSE                     FALSE                           FALSE                           
        RScripts/ridge_lasso_function4.R RScripts/rlm_function.R RScripts/rlm_function2.R
value   ?                                ?                       ?                       
visible FALSE                            FALSE                   FALSE                   

Check parameters


### powers to try
powers <- seq(0.1, 0.9, by = 0.01)
powers2 <- 1

### Powers to Try
#powers <- seq(0.1, 0.9, by = 0.01)
#powers2 <-seq(1.5,3, by = 0.25)


### Lambda parameters
parameters <- c(
  #  seq(0.1, 2, by =0.1) ,  seq(2, 5, 0.5) ,
  seq(5, 29, 1)
  ,seq(30, 102, 4)
  ,seq(110, 1000, 15)
  ,seq(1000, 10020, 500)
)

### elasticnet parameters
alpha_parameters <- c(seq(0, 1, 0.25))

# For Testing Purposes
#alpha_parameters <- c(seq(1, 1, 1))

Testing Different Model Types

Chrome

Data Readin


start_time <- Sys.time()

Final_CLS_2022_Study_List_Non_Search_model_file_chrome_pre <-
  Final_CLS_2022_Study_List_Non_Search_model_file %>%
  filter(pa == "Chrome") %>%
  mutate(
    id2 = row_number()
  )

df_test <-
  Final_CLS_2022_Study_List_Non_Search_model_file_chrome_pre %>%
  select(
    region_v2, country, channel, tactic,
    cost_spent_on_exposed_group:absolute_lift
  )

iso_chrome <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1153)

iso_chrome$fit(df_test)

scores_train <- df_test %>%
  iso_chrome$predict() %>%
  arrange(desc(anomaly_score))

Final_CLS_2022_Study_List_Non_Search_model_file_chrome_pre2 <-
  Final_CLS_2022_Study_List_Non_Search_model_file_chrome_pre %>%
  left_join(scores_train, by = c("id2" = "id")) %>% 
  filter(average_depth > 3)


Final_CLS_2022_Study_List_Non_Search_model_file_chrome <-
  Final_CLS_2022_Study_List_Non_Search_model_file_chrome_pre2 %>%
  named_group_split(tactic)

Run Model



fits_non_search_chrome <- model_wrapper_function(df = Final_CLS_2022_Study_List_Non_Search_model_file_chrome,poly_ind = 0)

best_ind_non_search_chrome <- 
  lapply(1:length(Final_CLS_2022_Study_List_Non_Search_model_file_chrome), best_ind_function,df = fits_non_search_chrome,
         df2 = Final_CLS_2022_Study_List_Non_Search_model_file_chrome) 

coef_non_search_chrome <- best_ind_non_search_chrome %>% bind_rows #make a matrix of all coefs

best_fit_non_search_chrome <- best_ind_non_search_chrome %>%
  set_names(names_function(Final_CLS_2022_Study_List_Non_Search_model_file_chrome_pre, tactic))  

Create Graph Object

graph_list_chrome <- lapply(1:length(best_fit_non_search_chrome), graphing_function4, df1 = best_fit_non_search_chrome, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_chrome)
end_time <- Sys.time()

time_chrome = end_time - start_time

time_chrome

Cloud

Data Readin

start_time <- Sys.time()

Final_CLS_2022_Study_List_Non_Search_model_file_cloud_pre <-
  Final_CLS_2022_Study_List_Non_Search_model_file %>%
  filter(pa %in% c("Cloud GCP", "Cloud Workspace")) %>%
  mutate(
    pa = "Cloud",
    pa2 = "Cloud - All Channel"
  ) %>%
  mutate(
    id2 = row_number()
  )

df_test <-
  Final_CLS_2022_Study_List_Non_Search_model_file_cloud_pre %>%
  # select(-study_id, -id2, -region, -scaling_factor, -quarter, -pa, -study_name)
  select(
    region_v2, country, channel, tactic,
    # treatment_user_count:control,
    cost_spent_on_exposed_group:absolute_lift, parsed_type
  )

iso_cloud <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1153)

iso_cloud$fit(df_test)

scores_train <- df_test %>%
  iso_cloud$predict() %>%
  arrange(desc(anomaly_score))

Final_CLS_2022_Study_List_Non_Search_model_file_cloud_pre2 <-
  Final_CLS_2022_Study_List_Non_Search_model_file_cloud_pre %>%
  left_join(scores_train, by = c("id2" = "id"))

Final_CLS_2022_Study_List_Non_Search_model_file_cloud <-
  Final_CLS_2022_Study_List_Non_Search_model_file_cloud_pre2 %>%
  named_group_split(pa2)

Run Model

fits_non_search_cloud <- model_wrapper_function(df = Final_CLS_2022_Study_List_Non_Search_model_file_cloud,poly_ind = 0)

best_ind_non_search_cloud <- 
  lapply(1:length(Final_CLS_2022_Study_List_Non_Search_model_file_cloud), best_ind_function,df = fits_non_search_cloud,
         df2 = Final_CLS_2022_Study_List_Non_Search_model_file_cloud) 

coef_non_search_cloud <- best_ind_non_search_cloud %>% bind_rows #make a matrix of all coefs

best_fit_non_search_cloud <- best_ind_non_search_cloud %>%
  set_names(names_function(Final_CLS_2022_Study_List_Non_Search_model_file_cloud_pre, pa2))  

Create Graph Object

graph_list_cloud <- lapply(1:length(best_fit_non_search_cloud), graphing_function4, df1 = best_fit_non_search_cloud, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_cloud)
end_time <- Sys.time()

time_cloud = end_time - start_time

YouTube

Data Readin


start_time <- Sys.time()

Final_CLS_2022_Study_List_Non_Search_model_file_youtube_pre <-
  Final_CLS_2022_Study_List_Non_Search_model_file %>%
  filter(pa %in% c("YouTube TV", "YTMP")) %>%
  mutate(
    pa = "YouTube",
    pa2 = "YouTube"
  ) %>%
  #  filter(absolute_lift < 5000) %>%
  mutate(
    id2 = row_number()
  )

df_test <-
  Final_CLS_2022_Study_List_Non_Search_model_file_youtube_pre %>%
  # select(-study_id, -id2, -region, -scaling_factor, -quarter, -pa, -study_name)
  select(
    region_v2, country, channel, tactic,
    # treatment_user_count:control,
    cost_spent_on_exposed_group:absolute_lift, parsed_type
  )

iso_yt <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1153)

iso_yt$fit(df_test)

scores_train <- df_test %>%
  iso_yt$predict() %>%
  arrange(desc(anomaly_score))

Final_CLS_2022_Study_List_Non_Search_model_file_youtube_pre2 <-
  Final_CLS_2022_Study_List_Non_Search_model_file_youtube_pre %>%
  left_join(scores_train, by = c("id2" = "id")) %>%
  filter(average_depth > 3.89)

Final_CLS_2022_Study_List_Non_Search_model_file_youtube <-
  Final_CLS_2022_Study_List_Non_Search_model_file_youtube_pre2 %>%
  named_group_split(region_v2)

Run Model

fits_non_search_youtube <- model_wrapper_function(df = Final_CLS_2022_Study_List_Non_Search_model_file_youtube,poly_ind = 0)

best_ind_non_search_youtube <- 
  lapply(1:length(Final_CLS_2022_Study_List_Non_Search_model_file_youtube), best_ind_function,df = fits_non_search_youtube,
         df2 = Final_CLS_2022_Study_List_Non_Search_model_file_youtube) 

coef_non_search_youtube <- best_ind_non_search_youtube %>% bind_rows #make a matrix of all coefs

best_fit_non_search_youtube <- best_ind_non_search_youtube %>%
  set_names(names_function(Final_CLS_2022_Study_List_Non_Search_model_file_youtube_pre, pa2))  

Create Graph Object

graph_list_youtube <- lapply(1:length(best_fit_non_search_youtube), graphing_function4, df1 = best_fit_non_search_youtube, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_youtube)
end_time <- Sys.time()

time_youtube = end_time - start_time

DSM

Data Readin


start_time <- Sys.time()

Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre <-
  Final_CLS_2022_Study_List_Non_Search_model_file %>%
  filter(pa == "DSM") %>%
  filter(region_v2 != "APAC") %>%
  # filter(absolute_lift < 1000) # %>%
  # filter(study_id != '6297420') #%>%
  #  filter(study_id !='149161711') %>%
  #  filter(study_id != '148613002') %>%
  # filter(study_id !='3284625') %>%
  #  filter(study_id !='3329131')
  mutate(
    id2 = row_number()
  )

df_test <-
  Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre %>%
  # select(-study_id, -id2, -region, -scaling_factor, -quarter, -pa, -study_name)
  select(
    region_v2, country, channel, tactic,
    # treatment_user_count:control,
    cost_spent_on_exposed_group:absolute_lift
  )

iso_dsm <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1152)

iso_dsm$fit(df_test)

scores_train <- df_test %>%
  iso_dsm$predict() %>%
  arrange(desc(anomaly_score))

Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre2 <-
  Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre %>%
  left_join(scores_train, by = c("id2" = "id")) %>%
  filter(average_depth > 5)

Final_CLS_2022_Study_List_Non_Search_model_file_dsm <-
  Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre2 %>%
  named_group_split(region_v2, channel)

Run Model

fits_non_search_dsm <- model_wrapper_function(df = Final_CLS_2022_Study_List_Non_Search_model_file_dsm,poly_ind = 0)

best_ind_non_search_dsm <- 
  lapply(1:length(Final_CLS_2022_Study_List_Non_Search_model_file_dsm), best_ind_function,df = fits_non_search_dsm,
         df2 = Final_CLS_2022_Study_List_Non_Search_model_file_dsm)

coef_non_search_dsm <- best_ind_non_search_dsm %>% bind_rows #make a matrix of all coefs

best_fit_non_search_dsm <- best_ind_non_search_dsm %>%
  set_names(names_function(Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre, region_v2,channel))  

Create Graph Object

graph_list_dsm <- lapply(1:length(best_fit_non_search_dsm), graphing_function4, df1 = best_fit_non_search_dsm, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_dsm)
end_time <- Sys.time()

time_dsm = end_time - start_time

Pixel

Data Readin


start_time <- Sys.time()

Final_CLS_2022_Study_List_Non_Search_model_file_pixel_pre <-
  Final_CLS_2022_Study_List_Non_Search_model_file %>%
  filter(pa == "Pixel") %>%
  mutate(
    pa2 = "Pixel - All Channel"
  ) %>%
  #   filter(absolute_lift < 1000)  %>%
  # filter(study_id != '6297420') #%>%
  #  filter(study_id !='149161711') %>%
  #  filter(study_id != '148613002') %>%
  # filter(study_id !='3284625') %>%
  #  filter(study_id !='3329131')
  mutate(
    id2 = row_number()
  )

df_test <-
  Final_CLS_2022_Study_List_Non_Search_model_file_pixel_pre %>%
  # select(-study_id, -id2, -region, -scaling_factor, -quarter, -pa, -study_name)
  select(
    region_v2, country, channel, tactic,
    # treatment_user_count:control,
    cost_spent_on_exposed_group:absolute_lift
  )

iso_pixel <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1152)

iso_pixel$fit(df_test)

scores_train <- df_test %>%
  iso_pixel$predict() %>%
  arrange(desc(anomaly_score))

Final_CLS_2022_Study_List_Non_Search_model_file_pixel_pre2 <-
  Final_CLS_2022_Study_List_Non_Search_model_file_pixel_pre %>%
  left_join(scores_train, by = c("id2" = "id")) %>%
  filter(average_depth > 3.1)

Final_CLS_2022_Study_List_Non_Search_model_file_pixel_pre2


Final_CLS_2022_Study_List_Non_Search_model_file_pixel <-
  Final_CLS_2022_Study_List_Non_Search_model_file_pixel_pre2 %>%
  named_group_split(pa2)

Run Model

fits_non_search_pixel <- model_wrapper_function(df = Final_CLS_2022_Study_List_Non_Search_model_file_pixel,poly_ind = 0)

best_ind_non_search_pixel <- 
  lapply(1:length(Final_CLS_2022_Study_List_Non_Search_model_file_pixel), best_ind_function,df = fits_non_search_pixel,
         df2 = Final_CLS_2022_Study_List_Non_Search_model_file_pixel) 

coef_non_search_pixel <- best_ind_non_search_pixel %>% bind_rows #make a matrix of all coefs

best_fit_non_search_pixel <- best_ind_non_search_pixel %>%
  set_names(names_function(Final_CLS_2022_Study_List_Non_Search_model_file_pixel_pre, pa2))  

Create Graph Object

graph_list_pixel <- lapply(1:length(best_fit_non_search_pixel), graphing_function4, df1 = best_fit_non_search_pixel, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_pixel)
end_time <- Sys.time()

time_pixel = end_time - start_time

Fi

Data Readin


start_time <- Sys.time()

Final_CLS_2022_Study_List_Non_Search_model_file_fi_pre <-
  Final_CLS_2022_Study_List_Non_Search_model_file %>%
  filter(pa == "Google Fi") %>%
  mutate(
    pa2 = "Fi - All Channel"
  ) %>%
  #   filter(absolute_lift < 1000)  %>%
  # filter(study_id != '6297420') #%>%
  #  filter(study_id !='149161711') %>%
  #  filter(study_id != '148613002') %>%
  # filter(study_id !='3284625') %>%
  #  filter(study_id !='3329131')
  mutate(
    id2 = row_number()
  )

df_test <-
  Final_CLS_2022_Study_List_Non_Search_model_file_fi_pre %>%
  # select(-study_id, -id2, -region, -scaling_factor, -quarter, -pa, -study_name)
  select(
    region_v2, country, channel, tactic,
    # treatment_user_count:control,
    cost_spent_on_exposed_group:absolute_lift
  )

iso_fi <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1152)

iso_fi$fit(df_test)

scores_train <- df_test %>%
  iso_fi$predict() %>%
  arrange(desc(anomaly_score))

Final_CLS_2022_Study_List_Non_Search_model_file_fi_pre2 <-
  Final_CLS_2022_Study_List_Non_Search_model_file_fi_pre %>%
  left_join(scores_train, by = c("id2" = "id")) %>%
  filter(average_depth > 4.75)

Final_CLS_2022_Study_List_Non_Search_model_file_fi_pre2


Final_CLS_2022_Study_List_Non_Search_model_file_fi <-
  Final_CLS_2022_Study_List_Non_Search_model_file_fi_pre2 %>%
  named_group_split(channel)

Run Model

fits_non_search_fi <- model_wrapper_function(df = Final_CLS_2022_Study_List_Non_Search_model_file_fi,poly_ind = 0)

best_ind_non_search_fi <- 
  lapply(1:length(Final_CLS_2022_Study_List_Non_Search_model_file_fi), best_ind_function,df = fits_non_search_fi,
         df2 = Final_CLS_2022_Study_List_Non_Search_model_file_fi) 

coef_non_search_fi <- best_ind_non_search_fi %>% bind_rows #make a matrix of all coefs

best_fit_non_search_fi <- best_ind_non_search_fi %>%
  set_names(names_function(Final_CLS_2022_Study_List_Non_Search_model_file_fi_pre, pa2))  

Create Graph Object

graph_list_fi <- lapply(1:length(best_fit_non_search_fi), graphing_function4, df1 = best_fit_non_search_fi, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_fi)
end_time <- Sys.time()

time_fi = end_time - start_time

SMB - QLeads

Data Readin


start_time <- Sys.time()

Final_CLS_2022_Study_List_Non_Search_model_file_smbq_pre <-
  Final_CLS_2022_Study_List_Non_Search_model_file %>%
  filter(grouped_conversion == 'Lena Q Lead') %>%
  mutate(
    pa2 = "SMB - Q-Lead"
  ) %>%
  #   filter(absolute_lift < 1000)  %>%
  # filter(study_id != '6297420') #%>%
  #  filter(study_id !='149161711') %>%
  #  filter(study_id != '148613002') %>%
  # filter(study_id !='3284625') %>%
  #  filter(study_id !='3329131')
  mutate(
    id2 = row_number()
  )

df_test <-
  Final_CLS_2022_Study_List_Non_Search_model_file_smbq_pre %>%
  # select(-study_id, -id2, -region, -scaling_factor, -quarter, -pa, -study_name)
  select(
    region_v2, country, channel, tactic,
    # treatment_user_count:control,
    cost_spent_on_exposed_group:absolute_lift
  )

iso_smbq <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1152)

iso_smbq$fit(df_test)

scores_train <- df_test %>%
  iso_smbq$predict() %>%
  arrange(desc(anomaly_score))

Final_CLS_2022_Study_List_Non_Search_model_file_smbq_pre2 <-
  Final_CLS_2022_Study_List_Non_Search_model_file_smbq_pre %>%
  left_join(scores_train, by = c("id2" = "id")) %>% 
  filter(average_depth > 1)

Final_CLS_2022_Study_List_Non_Search_model_file_smbq <-
  Final_CLS_2022_Study_List_Non_Search_model_file_smbq_pre2 %>%
  named_group_split(pa2)

Run Model

fits_non_search_smbq <- model_wrapper_function(df = Final_CLS_2022_Study_List_Non_Search_model_file_smbq,poly_ind = 0)

best_ind_non_search_smbq <- 
  lapply(1:length(Final_CLS_2022_Study_List_Non_Search_model_file_smbq), best_ind_function,df = fits_non_search_smbq,
         df2 = Final_CLS_2022_Study_List_Non_Search_model_file_smbq) 

coef_non_search_smbq <- best_ind_non_search_smbq %>% bind_rows #make a matrix of all coefs

best_fit_non_search_smbq <- best_ind_non_search_smbq %>%
  set_names(names_function(Final_CLS_2022_Study_List_Non_Search_model_file_smbq_pre, pa2))  

Create Graph Object

graph_list_smbq <- lapply(1:length(best_fit_non_search_smbq), graphing_function4, df1 = best_fit_non_search_smbq, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_smbq)
end_time <- Sys.time()

time_smbq = end_time - start_time

SMB - BLeads

Data Readin


start_time <- Sys.time()

Final_CLS_2022_Study_List_Non_Search_model_file_smbb_pre <-
  Final_CLS_2022_Study_List_Non_Search_model_file %>%
  filter(pa == "SMB" & grouped_conversion == 'Lena B Lead') %>%
  mutate(
    pa2 = "SMB - B-Lead"
  ) %>%
  #   filter(absolute_lift < 1000)  %>%
  # filter(study_id != '6297420') #%>%
  #  filter(study_id !='149161711') %>%
  #  filter(study_id != '148613002') %>%
  # filter(study_id !='3284625') %>%
  #  filter(study_id !='3329131')
  mutate(
    id2 = row_number()
  )

df_test <-
  Final_CLS_2022_Study_List_Non_Search_model_file_smbb_pre %>%
  # select(-study_id, -id2, -region, -scaling_factor, -quarter, -pa, -study_name)
  select(
    region_v2, country, channel, tactic,
    # treatment_user_count:control,
    cost_spent_on_exposed_group:absolute_lift
  )

iso_smbb <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1152)

iso_smbb$fit(df_test)

scores_train <- df_test %>%
  iso_smbb$predict() %>%
  arrange(desc(anomaly_score))

Final_CLS_2022_Study_List_Non_Search_model_file_smbb_pre2 <-
  Final_CLS_2022_Study_List_Non_Search_model_file_smbb_pre %>%
  left_join(scores_train, by = c("id2" = "id")) %>% 
  filter(average_depth > 4)

Final_CLS_2022_Study_List_Non_Search_model_file_smbb <-
  Final_CLS_2022_Study_List_Non_Search_model_file_smbb_pre2 %>%
  named_group_split(channel)

Run Model

fits_non_search_smbb <- model_wrapper_function(df = Final_CLS_2022_Study_List_Non_Search_model_file_smbb,poly_ind = 0)

best_ind_non_search_smbb <- 
  lapply(1:length(Final_CLS_2022_Study_List_Non_Search_model_file_smbb), best_ind_function,df = fits_non_search_smbb,
         df2 = Final_CLS_2022_Study_List_Non_Search_model_file_smbb) 

coef_non_search_smbb <- best_ind_non_search_smbb %>% bind_rows #make a matrix of all coefs

best_fit_non_search_smbb <- best_ind_non_search_smbb %>%
  set_names(names_function(Final_CLS_2022_Study_List_Non_Search_model_file_smbb_pre, channel))  

Create Graph Object

graph_list_smbb <- lapply(1:length(best_fit_non_search_smbb), graphing_function4, df1 = best_fit_non_search_smbb, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_smbb)
end_time <- Sys.time()

time_smbb = end_time - start_time

Export all graph lists

graph_names <- mget(ls(pat = 'graph_list_'))
   
df_names <- mget(setdiff(ls(pattern = 'Final_CLS_2022_Study_List_Non_Search_model_file_'), ls(pattern = "pre")))

#rm(Final_CLS_2022_Study_List_Non_Search_model_file_Chrome,Final_CLS_2022_Study_List_Non_Search_model_file_Cloud,Final_CLS_2022_Study_List_Non_Search_model_file_YouTube)

#lapply(1:length(graph_names),
#      function(j) {
#lapply(1:length(df_names[[j]]),export_rplots_function2,starting_name = "Non_Search_",folder_name = folder_name,df_list = #df_names[[j]],graphing_list = graph_names[j][[1]])
#      }
#       )

Grid of all Response Curves

Sub Plot Documentation

Coef Matrix

Graphs with Anomaly Scores

graph_list.fi <- lapply(1:length(best_fit_non_search_fi), graphing_function4_w_anom, df1 = best_fit_non_search_fi, df2 = Final_CLS_2022_Study_List_Non_Search_model_file_fi)

### Add GG Text Repel
ggplotly(graph_list.fi[[3]])

Create all Response Curves - Ridge/Lasso


start_time <- Sys.time()

fits.non.search.RIDGE_LASSO <- lapply(
  1:length(df_names),
  function(i) {
    model_wrapper_function(df = df_names[i][[1]],poly_ind = 0)
  }
)

Create all Response Curves - RLM



start_time <- Sys.time()

fits.non.search.RLM <- lapply(
  1:length(df_names),
  function(i) {
    model_wrapper_function2(df = df_names[i][[1]])
  }
)

end_time <- Sys.time()

combined_rlm_time <- start_time - end_time

best.ind.non.search.RLM <- lapply(
  1:length(df_names),
  function(i) {   
  lapply(1:length(df_names[i][[1]]), best_ind_function,df = fits.non.search.RLM[i][[1]],
         df2 = df_names[i][[1]])
  }
)

coef.non.search.RLM <- lapply(
  1:length(df_names),
  function (i){
  best.ind.non.search.RLM[i][[1]] %>% bind_rows
  }
) %>%
  bind_rows() %>% 
  as.data.frame() %>% 
  mutate(
    cost_p2 = 0,
    lambda = 0,
    alpha = 0,
    powers2 = 0
  ) %>% 
  select(one_of(colnames(coef.2_matrix)))


best.fit.non.search.RLM <- lapply(1:length(df_names),
      function(j) {
lapply(1:length(best.ind.non.search.RLM[[j]]),
      function(i){
        best.ind.non.search.RLM[j][[1]][i] %>% 
        set_names(nm = best.ind.non.search.RLM[j][[1]][[i]]["model"])
      } 
)
      }
       )


  

-combined_ridge_time+combined_rlm_time
Time difference of 32.768 mins

graph.list.rlm <- lapply(1:length(df_names),
      function(i){
      lapply(1:length(best.fit.non.search.RLM[i][[1]]), graphing_function_rlm, df1= best.fit.non.search.RLM[i],df2 = df_names[i])
      } 
)


graph.list.RIDGE_LASSO <- lapply(1:length(df_names),
      function(i){
      lapply(1:length(best.fit.non.search.RIDGE_LASSO[i][[1]]), graphing_function_elasticnet, df1= best.fit.non.search.RIDGE_LASSO[i],df2 = df_names[i])
      } 
)

Export all Plots


folder_name1 <- paste0("Output/", "outputfiles_", Sys.Date(), "_", "RLM", "/")
dir.create(folder_name1) # it will throw a warning if folder exists
Warning in dir.create(folder_name1) :
  'Output\outputfiles_2022-11-08_RLM' already exists
lapply(1:length(df_names),
      function(j) {
lapply(1:length(df_names[[j]]),export_rplots_function2,starting_name = "Non_Search_",folder_name = folder_name1,df_list = df_names[[j]],graphing_list = graph.list.rlm[j][[1]])
      }
       )
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
[[1]]
[[1]][[1]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_Chrome_All_Channel.png"

[[1]][[2]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_Chrome_non-REMK.png"

[[1]][[3]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_Chrome_REMK.png"


[[2]]
[[2]][[1]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_Cloud_Cloud_-_All_Channel.png"


[[3]]
[[3]][[1]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_DSM_EMEA__DISCOVERY.png"

[[3]][[2]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_DSM_EMEA__DISPLAY.png"

[[3]][[3]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_DSM_EMEA__YOUTUBE.png"

[[3]][[4]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_DSM_NA__DISCOVERY.png"

[[3]][[5]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_DSM_NA__DISPLAY.png"

[[3]][[6]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_DSM_NA__YOUTUBE.png"


[[4]]
[[4]][[1]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_Google_Fi_DISCOVERY.png"

[[4]][[2]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_Google_Fi_DISPLAY.png"

[[4]][[3]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_Google_Fi_YOUTUBE.png"


[[5]]
[[5]][[1]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_Pixel_Pixel_-_All_Channel.png"


[[6]]
[[6]][[1]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_SMB_DISCOVERY.png"

[[6]][[2]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_SMB_DISPLAY.png"

[[6]][[3]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_SMB_YOUTUBE.png"


[[7]]
[[7]][[1]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_SMB-QLead_SMB_-_Q-Lead.png"


[[8]]
[[8]][[1]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_YouTube_APAC.png"

[[8]][[2]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_YouTube_EMEA.png"

[[8]][[3]]
[1] "Output/outputfiles_2022-11-08_RLM/Non_Search_YouTube_NA.png"

folder_name2 <- paste0("Output/", "outputfiles_", Sys.Date(), "_", "ElasticNet", "/")
dir.create(folder_name2) # it will throw a warning if folder exists
Warning in dir.create(folder_name2) :
  'Output\outputfiles_2022-11-08_ElasticNet' already exists
lapply(1:length(df_names),
      function(j) {
lapply(1:length(df_names[[j]]),export_rplots_function2,starting_name = "Non_Search_",folder_name = folder_name2,df_list = df_names[[j]],graphing_list = graph.list.RIDGE_LASSO[j][[1]])
      }
       )
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
Saving 18.8 x 12.5 in image
[[1]]
[[1]][[1]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_Chrome_All_Channel.png"

[[1]][[2]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_Chrome_non-REMK.png"

[[1]][[3]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_Chrome_REMK.png"


[[2]]
[[2]][[1]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_Cloud_Cloud_-_All_Channel.png"


[[3]]
[[3]][[1]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_DSM_EMEA__DISCOVERY.png"

[[3]][[2]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_DSM_EMEA__DISPLAY.png"

[[3]][[3]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_DSM_EMEA__YOUTUBE.png"

[[3]][[4]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_DSM_NA__DISCOVERY.png"

[[3]][[5]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_DSM_NA__DISPLAY.png"

[[3]][[6]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_DSM_NA__YOUTUBE.png"


[[4]]
[[4]][[1]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_Google_Fi_DISCOVERY.png"

[[4]][[2]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_Google_Fi_DISPLAY.png"

[[4]][[3]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_Google_Fi_YOUTUBE.png"


[[5]]
[[5]][[1]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_Pixel_Pixel_-_All_Channel.png"


[[6]]
[[6]][[1]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_SMB_DISCOVERY.png"

[[6]][[2]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_SMB_DISPLAY.png"

[[6]][[3]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_SMB_YOUTUBE.png"


[[7]]
[[7]][[1]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_SMB-QLead_SMB_-_Q-Lead.png"


[[8]]
[[8]][[1]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_YouTube_APAC.png"

[[8]][[2]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_YouTube_EMEA.png"

[[8]][[3]]
[1] "Output/outputfiles_2022-11-08_ElasticNet/Non_Search_YouTube_NA.png"

Show Graphs

lapply(1:length(df_names),
function(j){
  subplot(graph.list.rlm[j][[1]], nrows = length(graph.list.rlm[j][[1]]))
}
)
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

[[7]]

[[8]]
lapply(1:length(df_names),
function(i){
#p1 = graph_names[i][[1]]
do.call(grid.arrange,graph.list.rlm[i][[1]])
#return(grid.arrange(grobs = p1))
}
)
[[1]]
TableGrob (3 x 1) "arrange": 3 grobs

[[2]]
TableGrob (1 x 1) "arrange": 1 grobs

[[3]]
TableGrob (3 x 2) "arrange": 6 grobs

[[4]]
TableGrob (3 x 1) "arrange": 3 grobs

[[5]]
TableGrob (1 x 1) "arrange": 1 grobs

[[6]]
TableGrob (3 x 1) "arrange": 3 grobs

[[7]]
TableGrob (1 x 1) "arrange": 1 grobs

[[8]]
TableGrob (3 x 1) "arrange": 3 grobs
NA

lapply(1:length(df_names),
function(j){
  subplot(graph.list.RIDGE_LASSO[j][[1]], nrows = length(graph.list.RIDGE_LASSO[j][[1]]))
}
)
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

[[7]]

[[8]]
lapply(1:length(df_names),
function(i){
#p1 = graph_names[i][[1]]
do.call(grid.arrange,graph.list.RIDGE_LASSO[i][[1]])
#return(grid.arrange(grobs = p1))
}
)
[[1]]
TableGrob (3 x 1) "arrange": 3 grobs

[[2]]
TableGrob (1 x 1) "arrange": 1 grobs

[[3]]
TableGrob (3 x 2) "arrange": 6 grobs

[[4]]
TableGrob (3 x 1) "arrange": 3 grobs

[[5]]
TableGrob (1 x 1) "arrange": 1 grobs

[[6]]
TableGrob (3 x 1) "arrange": 3 grobs

[[7]]
TableGrob (1 x 1) "arrange": 1 grobs

[[8]]
TableGrob (3 x 1) "arrange": 3 grobs
NA

Testing Metafor Package


p_load(lmer4)
Installing package into ‘C:/Users/Admin/Documents/R/win-library/4.1’
(as ‘lib’ is unspecified)
Warning: package ‘lmer4’ is not available for this version of R

A version of this package for your version of R might be available elsewhere,
see the ideas at
https://cran.r-project.org/doc/manuals/r-patched/R-admin.html#Installing-packages
Warning: unable to access index for repository http://www.stats.ox.ac.uk/pub/RWin/bin/windows/contrib/4.1:
  cannot open URL 'http://www.stats.ox.ac.uk/pub/RWin/bin/windows/contrib/4.1/PACKAGES'
Warning in p_install(package, character.only = TRUE, ...) : 
Warning in library(package, lib.loc = lib.loc, character.only = TRUE, logical.return = TRUE,  :
  there is no package called ‘lmer4’
Warning in p_load(lmer4) : Failed to install/load:
lmer4
p_load(metaforest)
Installing package into ‘C:/Users/Admin/Documents/R/win-library/4.1’
(as ‘lib’ is unspecified)
also installing the dependencies ‘metadat’, ‘mathjaxr’, ‘metafor’

Warning: unable to access index for repository http://www.stats.ox.ac.uk/pub/RWin/bin/windows/contrib/4.1:
  cannot open URL 'http://www.stats.ox.ac.uk/pub/RWin/bin/windows/contrib/4.1/PACKAGES'

  There is a binary version available but the source version is later:
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.1/mathjaxr_1.6-0.zip'
Content type 'application/zip' length 970577 bytes (947 KB)
downloaded 947 KB

trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.1/metafor_3.8-1.zip'
Content type 'application/zip' length 4483503 bytes (4.3 MB)
downloaded 4.3 MB

trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.1/metaforest_0.1.3.zip'
Content type 'application/zip' length 217909 bytes (212 KB)
downloaded 212 KB
package ‘mathjaxr’ successfully unpacked and MD5 sums checked
package ‘metafor’ successfully unpacked and MD5 sums checked
package ‘metaforest’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\Admin\AppData\Local\Temp\RtmpGGjNkA\downloaded_packages
installing the source package ‘metadat’

trying URL 'https://cran.rstudio.com/src/contrib/metadat_1.2-0.tar.gz'
Content type 'application/x-gzip' length 964808 bytes (942 KB)
downloaded 942 KB
* installing *source* package 'metadat' ...
** package 'metadat' successfully unpacked and MD5 sums checked
** using staged installation
** R
** data
*** moving datasets to lazyload DB
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
  converting help for package 'metadat'
    finding HTML links ... done
    dat.aloe2013                            html  
    dat.anand1999                           html  
    dat.assink2016                          html  
    dat.axfors2021                          html  
    dat.bakdash2021                         html  
    dat.baker2009                           html  
    dat.bangertdrowns2004                   html  
    dat.baskerville2012                     html  
    dat.bcg                                 html  
    dat.begg1989                            html  
    dat.berkey1998                          html  
    dat.besson2016                          html  
    dat.bonett2010                          html  
    dat.bornmann2007                        html  
    dat.bourassa1996                        html  
    dat.cannon2006                          html  
    dat.cohen1981                           html  
    dat.colditz1994                         html  
    dat.collins1985a                        html  
    dat.collins1985b                        html  
    dat.craft2003                           html  
    dat.crede2010                           html  
    dat.curtis1998                          html  
    dat.dagostino1998                       html  
    dat.damico2009                          html  
    dat.debruin2009                         html  
    dat.dogliotti2014                       html  
    dat.dong2013                            html  
    dat.dorn2007                            html  
    dat.egger2001                           html  
    dat.fine1993                            html  
    dat.franchini2012                       html  
    dat.frank2008                           html  
    dat.gibson2002                          html  
    dat.graves2010                          html  
    dat.gurusamy2011                        html  
    dat.hackshaw1998                        html  
    dat.hahn2001                            html  
    dat.hannum2020                          html  
    dat.hart1999                            html  
    dat.hartmannboyce2018                   html  
    dat.hasselblad1998                      html  
    dat.hine1989                            html  
    dat.ishak2007                           html  
    dat.kalaian1996                         html  
    dat.kearon1998                          html  
    dat.knapp2017                           html  
    dat.konstantopoulos2011                 html  
    dat.landenberger2005                    html  
    dat.laopaiboon2015                      html  
    dat.lau1992                             html  
    dat.lee2004                             html  
    dat.lehmann2018                         html  
    dat.li2007                              html  
    dat.lim2014                             html  
    dat.linde2005                           html  
    dat.linde2015                           html  
    dat.linde2016                           html  
    dat.lopez2019                           html  
    dat.maire2019                           html  
    dat.mccurdy2020                         html  
    dat.mcdaniel1994                        html  
    dat.michael2013                         html  
    dat.molloy2014                          html  
    dat.moura2021                           html  
    dat.nakagawa2007                        html  
    dat.nielweise2007                       html  
    dat.nielweise2008                       html  
    dat.normand1999                         html  
    dat.obrien2003                          html  
    dat.pagliaro1992                        html  
    dat.pignon2000                          html  
    dat.pritz1997                           html  
    dat.raudenbush1985                      html  
    dat.riley2003                           html  
    dat.senn2013                            html  
    dat.stowe2010                           html  
    dat.tannersmith2016                     html  
    dat.vanhowe1999                         html  
    dat.viechtbauer2021                     html  
    dat.white2020                           html  
    dat.woods2010                           html  
    dat.yusuf1985                           html  
    datsearch                               html  
    metadat-package                         html  
    prep_dat                                html  
** building package indices
** testing if installed package can be loaded from temporary location
*** arch - i386
*** arch - x64
** testing if installed package can be loaded from final location
*** arch - i386
*** arch - x64
** testing if installed package keeps a record of temporary installation path
* DONE (metadat)

The downloaded source packages are in
    ‘C:\Users\Admin\AppData\Local\Temp\RtmpGGjNkA\downloaded_packages’

metaforest installed
Warning: package ‘metaforest’ was built under R version 4.1.3
Warning: package ‘metafor’ was built under R version 4.1.3

Testing on DSM Data

Load in Data



Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre <-
  Final_CLS_2022_Study_List_Non_Search_model_file %>%
  filter(pa == "DSM") %>%
  filter(region_v2 != "APAC") %>%
  # filter(absolute_lift < 1000) # %>%
  # filter(study_id != '6297420') #%>%
  #  filter(study_id !='149161711') %>%
  #  filter(study_id != '148613002') %>%
  # filter(study_id !='3284625') %>%
  #  filter(study_id !='3329131')
  mutate(
    id2 = row_number()
  )

df_test <-
  Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre %>%
  # select(-study_id, -id2, -region, -scaling_factor, -quarter, -pa, -study_name)
  select(
    region_v2, country, channel, tactic,
    # treatment_user_count:control,
    cost_spent_on_exposed_group:absolute_lift
  )

iso_dsm <- isolationForest$new(sample_size = nrow(df_test), num_trees = 10000, seed = 1152)

iso_dsm$fit(df_test)

scores_train <- df_test %>%
  iso_dsm$predict() %>%
  arrange(desc(anomaly_score))

Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4_V1 <-
  Final_CLS_2022_Study_List_Non_Search_model_file_dsm_pre %>%
  left_join(scores_train, by = c("id2" = "id")) %>%
 filter(average_depth > 5.1)


Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4 <-
  Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4_V1 %>%
  named_group_split(region_v2)

Standardize Data

Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4_V1 %>% 
  mutate(
    
  )

Run a Fixed-Effects Model

Documentation



#df_smd 


i = 1

yi_DSM = Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4[[i]]['absolute_lift'] %>% unlist()
vi_DSM = Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4[[i]]['Significant_Spend']^1 %>% unlist()
split2 = factor(Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4[[i]]['channel'] %>% unlist(),labels = unique(Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4[[i]]['channel']) %>% unlist())


m_reg <- rma(yi = yi_DSM,     # The d-column of the df, which contains Cohen's d
         vi = vi_DSM   # The vi-column of the df, which contains the variances
         ,mods = ~split2-1 #to remove intercept between slopes
         )  
Warning: There are outcomes with non-positive sampling variances.
Warning: Cannot compute QE-test, I^2, or H^2 when there are non-positive sampling variances in the data.
       

mod1_test

Mixed-Effects Model (k = 26; tau^2 estimator: REML)

tau^2 (estimated amount of residual heterogeneity):     14491.7080 (SE = 25164.4568)
tau (square root of estimated tau^2 value):             120.3815
I^2 (residual heterogeneity / unaccounted variability): 16.12%
H^2 (unaccounted variability / sampling variability):   1.19
R^2 (amount of heterogeneity accounted for):            87.03%

Test for Residual Heterogeneity:
QE(df = 23) = 32.2909, p-val = 0.0942

Test of Moderators (coefficients 2:3):
QM(df = 2) = 25.4474, p-val < .0001

Model Results:

---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#rm(Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4_V1)#,mod1_test, i)

predict(mod1_test)
forest(mod1_test, slab = Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4[[i]]['study_name'] %>% unlist(), addcred = TRUE)

Additional Test


# Specify basic plot, mapping sex to the x-axis, effect size 'd' to the y-axis,
# and 'weights' to the weight parameter.

Final_CLS_2022_Study_List_Non_Search_model_file_dsm_Meta4[[i]] %>% 
  ggplot()+
  aes(
    x = cost_spent_on_exposed_group,
    y = absolute_lift,
    size = 1/sqrt(cost_spent_on_exposed_group)
  ) +
  geom_point(shape = 1) + # Add scatter
  geom_abline(intercept = m_reg$b[1], slope = m_reg$b[3]) + # Add regression line
  theme_bw() + # Apply black and white theme
  theme(legend.position = "none") # Remove legend
LS0tDQp0aXRsZTogIjAzX0NMU19TcGVuZF9SZXNwb25zZV9DdXJ2ZXNfTm9fUG9seSINCmF1dGhvcjogIkVzc2VuY2UgR2xvYmFsIEFkdmFuY2VkIEFuYWx5dGljcyBUZWFtIg0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IG5vDQogICAgdGhlbWU6IGNlcnVsZWFuDQogICAgaGlnaGxpZ2h0OiB6ZW5idXJuDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpvcHRpb25zKGtuaXRyLnRhYmxlLmZvcm1hdCA9ICJodG1sIikNCm9wdGlvbnMoZGlnaXRzID0gNSkNCm9wdGlvbnMoc2NpcGVuID0gMTAwKQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHRpZHkub3B0cyA9IGxpc3Qod2lkdGguY3V0b2ZmID0gODApLCB0aWR5ID0gVFJVRSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcud2lkdGggPSAxNSkNCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcuaGVpZ2h0ID0gMTApDQojIGluc3RhbGwucGFja2FnZXMoInBhY21hbiIpDQpsaWJyYXJ5KHBhY21hbikgIyBmb3IgcXVpY2sgbG9hZC9pbnN0YWxsIG9mIHBhY2thZ2VzDQpwX2xvYWQoZHBseXIsIHJlYWRyLCB0aWR5dmVyc2UsIHJldGljdWxhdGUsIGx1YnJpZGF0ZSwgamFuaXRvciwgc3FsZGYsIGdvb2dsZXNoZWV0czQpDQpwX2xvYWQoc2tpbXIsIHNwbGl0c3RhY2tzaGFwZSwgc3RyaW5nciwgcnFkYXRhdGFibGUpDQpwX2xvYWQobW9tZW50cykNCnBfbG9hZChrYWJsZUV4dHJhKQ0KcF9sb2FkKGdncGxvdDIsIHBsb3RseSwgZWNoYXJ0czRyLCBnZ3B1YnIsIGZvcmNhdHMsIHNjYWxlcywgUkNvbG9yQnJld2VyLGdyaWRFeHRyYSkNCnBfbG9hZChnZ3RoZW1lcykNCnBfbG9hZChjYXJldCwgcmVjaXBlcykNCnBfbG9hZChnbG1uZXQpDQpwX2xvYWQoZWxhc3RpY25ldCkNCnBfbG9hZChNZXRyaWNzKQ0KcF9sb2FkKGZhc3REdW1taWVzKQ0KcF9sb2FkKGJyb29tKQ0KcF9sb2FkKGh0bWx3aWRnZXRzKQ0KcF9sb2FkKHNvbGl0dWRlKQ0KcF9sb2FkKG1sYmVuY2gpDQpwX2xvYWQodXdvdCkNCmBgYA0KDQojIFVzZSBEYXRhc2V0IGNyZWF0ZWQgZnJvbSAwMl9DTFNfRGF0YV9TdW1tYXJ5XzIwMjJfMDkxNF9EYXRhX0FuYWx5c2lzIEZpbGUNCg0KIyMgTG9hZGluZyBEYXRhDQoNCiMjIyBMb2FkIEdvb2dsZSBTaGVldA0KDQpgYGB7cn0NCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlIDwtIHJlYWRfc2hlZXQoDQogICJodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9zcHJlYWRzaGVldHMvZC8xTjQ4clRlcTdtZDB2OHc4cEdfOFhJaXVhcFBIUUFlTzVXb1dJQjNlYWNlSS9lZGl0I2dpZD0xNDQ5MzUxMzc3IiwNCiAgc2hlZXQgPSAiRmluYWxEYXRhc2V0XzIwMjJfVXBkYXRlIg0KKSAlPiUNCiAgbXV0YXRlKA0KICAgIFNpZ25pZmljYW50X1NwZW5kID0NCiAgICAgIGFzLm51bWVyaWMoDQogICAgICAgIGNhc2Vfd2hlbigNCiAgICAgICAgICBwcm9iYWJpbGl0eV9vZl9saWZ0ID49IDAuOSB+IDEsDQogICAgICAgICAgVFJVRSB+IDANCiAgICAgICAgKQ0KICAgICAgKSwNCiAgICBjb3VudHJ5ID0gY2FzZV93aGVuKA0KICAgICAgY291bnRyeSA9PSAiTkEiIH4gIlVTIiwNCiAgICAgIFRSVUUgfiBjb3VudHJ5DQogICAgKSwNCiAgICByZWdpb25fdjIgPSBjYXNlX3doZW4oDQogICAgICBjb3VudHJ5ID09ICJVUyIgfiAiTkEiLA0KICAgICAgY291bnRyeSA9PSAiQ0EiIH4gIk5BIiwNCiAgICAgIGNvdW50cnkgPT0gIlVTICsgQ0EiIH4gIk5BIiwNCiAgICAgIFRSVUUgfiByZWdpb24NCiAgICApDQogICkgJT4lDQogIGZpbHRlcihjaGFubmVsICE9ICJTZWFyY2giKSAlPiUNCiAgIyBmaWx0ZXIgb3V0IHN0dWRpZXMgd2l0aG91dCByZXBvcnRlZCBsaWZ0cw0KICBmaWx0ZXIoZXhwb3NlZCAhPSAtMSkgJT4lDQogICMgZmlsdGVyIG91dCBnb29nbGUgcGF5IHN0dWR5DQogIGZpbHRlcihzdHVkeV9pZCAhPSAiMTQ5MTQyMjE3IikgJT4lDQogICMgZmlsdGVyIG91dCB2ZXJ5IG5lZ2F0aXZlIGFic29sdXRlIGxpZnRzDQogIGZpbHRlcihhYnNvbHV0ZV9saWZ0ID4gLTEwMDApICU+JQ0KICBtdXRhdGUoDQogICAgcGEgPSBjYXNlX3doZW4oDQogICAgICBwYSA9PSAiR29vZ2xlIEFkcyIgfiAiU01CIiwgIyBTdGVwIDENCiAgICAgIHBhID09ICJZb3VUdWJlIiAmIGNvbnZlcnNpb24gIT0gIlR5cGUgMjU2NTIyOTQyIChbTUNDXSBZb3VUdWJlIFRWIC0gV2ViIC0gVHJpYWwgU3RhcnQpIiB+ICJZVE1QIiwgIyBTdGVwIDINCiAgICAgIHBhID09ICJZb3VUdWJlIFByZW1pdW0iIH4gIllUTVAiLCAjIFN0ZXAgMg0KICAgICAgY29udmVyc2lvbiA9PSAiVHlwZSAyNTY1MjI5NDIgKFtNQ0NdIFlvdVR1YmUgVFYgLSBXZWIgLSBUcmlhbCBTdGFydCkiIH4gIllvdVR1YmUgVFYiLCAjIFN0ZXAgMg0KICAgICAgcGEgPT0gIkNsb3VkIiAmIGNvbnZlcnNpb24gIT0gIlR5cGUgMTQyNTc4MDMgKEVudGVycHJpc2UgLSBBcHBzIC0gU2lnbnVwIENvbmZpcm0gLSBVbmlxdWUpIiB+ICJDbG91ZCBXb3Jrc3BhY2UiLCAjIFN0ZXAgMw0KICAgICAgcGEgPT0gIkNsb3VkIiAmIGNvbnZlcnNpb24gPT0gIlR5cGUgMTQyNTc4MDMgKEVudGVycHJpc2UgLSBBcHBzIC0gU2lnbnVwIENvbmZpcm0gLSBVbmlxdWUpIiB+ICJDbG91ZCBHQ1AiLCAjIFN0ZXAgMw0KICAgICAgcGEgPT0gIlByb2plY3QgRmkiIH4gIkdvb2dsZSBGaSIsICMgU3RlcCA0DQogICAgICBwYSA9PSAiR29vZ2xlIENocm9tZSIgfiAiQ2hyb21lIiwNCiAgICAgIFRSVUUgfiBwYQ0KICAgICkNCiAgKSAlPiUNCiAgbXV0YXRlKA0KICAgIHBhcnNlZF90eXBlID0gcGFyc2VfbnVtYmVyKGNvbnZlcnNpb24pLA0KICAgIGdyb3VwZWRfY29udmVyc2lvbiA9IGNhc2Vfd2hlbigNCiAgICAgIGNvbnZlcnNpb24gJWluJSBjKCJDaHJvbWVib29rIE1pY3Jvc2l0ZSBSZWZlcnJhbCBDbGlja3MgUTQgMjAxNSIsICJUeXBlIDI1MTQyMjcyOSAoQ2hyb21lYm9va3MgTWljcm9zaXRlIFJlZmVycmFsIENsaWNrcyAoUTQgMjAxNykpIikgfiAiQ2hyb21lYm9vayBSZWZlcnJhbHMiLA0KICAgICAgY29udmVyc2lvbiAlaW4lIGMoIkRlc2t0b3AgRG93bmxvYWRzIiwgIlR5cGUgMTE1NDE1NDcgKERlc2t0b3AgRG93bmxvYWQpIikgfg0KICAgICAgICAiRGVza3RvcCBEb3dubG9hZHMiLA0KICAgICAgcGEgPT0gIlBpeGVsIiB+ICJNb2JpbGUgQ29udmVyc2lvbnMiLA0KICAgICAgcGEgPT0gIkRTTSIgfiAiTm9uLU1vYmlsZSBEZXZpY2UgQ29udmVyc2lvbnMiLA0KICAgICAgY29udmVyc2lvbiA9PSAiVHlwZSAzMDI5ODI5NTQgKExlbmEgLSBQIExlYWQpIiB+ICJMZW5hIFAgTGVhZCIsDQogICAgICBjb252ZXJzaW9uID09ICJUeXBlIDI4ODM0NzAwOCAoTEVOQSAtIEIgTGVhZCkiIH4gIkxlbmEgQiBMZWFkIiwNCiAgICAgIGNvbnZlcnNpb24gPT0gIlR5cGUgMjg4Njk3NjUzIChMRU5BIC0gUSBMZWFkKSIgfiAiTGVuYSBRIExlYWQiLA0KICAgICAgcGFyc2VkX3R5cGUgJWluJSBjKDE4MTI4Mzk5MywgODU1NTA4Njg2KSB+ICJXb3Jrc3BhY2UgRnJlZSBUcmlhbCBTdGFydCIsDQogICAgICBwYXJzZWRfdHlwZSA9PSAzMzA3NTU2NDEgfiAiTWljcm9zaXRlIENvbnZlcnNpb25zIiwNCiAgICAgIHBhcnNlZF90eXBlID09IDE0MjU3ODAzIH4gIkVudGVycHJpc2UgU2lnbnVwcyIsDQogICAgICBwYXJzZWRfdHlwZSA9PSAyODk2ODA3MTIgfiAiR29vZ2xlKGlPcykgRmlyc3QgT3BlbiIsDQogICAgICBwYXJzZWRfdHlwZSA9PSAyNTY1MjI5NDIgfiAiWW91VHViZSBUViAtIFdlYiAtIFRyaWFsIFN0YXJ0IiwNCiAgICAgIHBhcnNlZF90eXBlICVpbiUgYyg0NTIzOTE1MzQsIDIyMTQ5NzgzMywgMjc3MTUwMDc0KSB+ICJUcmlhbCBTaWdudXBzIENvbXBsZXRlIiwNCiAgICAgIFRSVUUgfiBjb252ZXJzaW9uDQogICAgKSwNCiAgICBwYSA9IGNhc2Vfd2hlbigNCiAgICAgIGNvbnZlcnNpb24gPT0gIlR5cGUgMjg4Njk3NjUzIChMRU5BIC0gUSBMZWFkKSIgfiAiU01CLVFMZWFkIiwNCiAgICAgIFRSVUUgfiBwYQ0KICAgICkNCiAgKSAlPiUNCiAgZmlsdGVyKGFic29sdXRlX2xpZnQgPiAwKQ0KDQoNCiMgYWxsLmVxdWFsKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlLEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF92MykNCmBgYA0KDQojIENyZWF0ZSBBbGwgUmVzcG9uc2UgQ3VydmVzIG9ubHkgbm9ybWFsIHBvd2Vycw0KDQojIyBGb2xkZXIgZm9yIGFsbCBPdXRwdXQgYW5kIHNjcmlwdHMNCg0KYGBge3J9DQpmb2xkZXJfbmFtZSA8LSBwYXN0ZTAoIk91dHB1dC8iLCAib3V0cHV0ZmlsZXNfIiwgU3lzLkRhdGUoKSwgIl8iLCAiUnVuMSIsICIvIikNCmRpci5jcmVhdGUoZm9sZGVyX25hbWUpICMgaXQgd2lsbCB0aHJvdyBhIHdhcm5pbmcgaWYgZm9sZGVyIGV4aXN0cw0KDQojIGZpbGUuc291cmNlczIgPC0gbGlzdC5maWxlcyhwYXRoID0gIk91dHB1dC9vdXRwdXRmaWxlc18yMDIyLTEwLTE0X1J1bjEvLyIsIHBhdHRlcm4gPSIuaHRtbHwucG5nIiwgZnVsbC5uYW1lcyA9IFRSVUUpDQpmaWxlLnNvdXJjZXMgPC0gbGlzdC5maWxlcyhwYXRoID0gIlJTY3JpcHRzLyIsIHBhdHRlcm4gPSAiKi5SIiwgZnVsbC5uYW1lcyA9IFRSVUUpDQpzYXBwbHkoZmlsZS5zb3VyY2VzLCBzb3VyY2UsIC5HbG9iYWxFbnYpDQpgYGANCg0KIyMgQ2hlY2sgcGFyYW1ldGVycw0KDQpgYGB7cn0NCg0KIyMjIHBvd2VycyB0byB0cnkNCnBvd2VycyA8LSBzZXEoMC4xLCAwLjksIGJ5ID0gMC4wMSkNCnBvd2VyczIgPC0gMQ0KDQojIyMgUG93ZXJzIHRvIFRyeQ0KI3Bvd2VycyA8LSBzZXEoMC4xLCAwLjksIGJ5ID0gMC4wMSkNCiNwb3dlcnMyIDwtc2VxKDEuNSwzLCBieSA9IDAuMjUpDQoNCg0KIyMjIExhbWJkYSBwYXJhbWV0ZXJzDQpwYXJhbWV0ZXJzIDwtIGMoDQogICMgIHNlcSgwLjEsIDIsIGJ5ID0wLjEpICwgIHNlcSgyLCA1LCAwLjUpICwNCiAgc2VxKDUsIDI5LCAxKQ0KICAsc2VxKDMwLCAxMDIsIDQpDQogICxzZXEoMTEwLCAxMDAwLCAxNSkNCiAgLHNlcSgxMDAwLCAxMDAyMCwgNTAwKQ0KKQ0KDQojIyMgZWxhc3RpY25ldCBwYXJhbWV0ZXJzDQphbHBoYV9wYXJhbWV0ZXJzIDwtIGMoc2VxKDAsIDEsIDAuMjUpKQ0KDQojIEZvciBUZXN0aW5nIFB1cnBvc2VzDQojYWxwaGFfcGFyYW1ldGVycyA8LSBjKHNlcSgxLCAxLCAxKSkNCg0KYGBgDQoNCiMjIFRlc3RpbmcgRGlmZmVyZW50IE1vZGVsIFR5cGVzDQoNCiMjIyBDaHJvbWUNCg0KIyMjIyBEYXRhIFJlYWRpbg0KDQpgYGB7cn0NCg0Kc3RhcnRfdGltZSA8LSBTeXMudGltZSgpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nocm9tZV9wcmUgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGUgJT4lDQogIGZpbHRlcihwYSA9PSAiQ2hyb21lIikgJT4lDQogIG11dGF0ZSgNCiAgICBpZDIgPSByb3dfbnVtYmVyKCkNCiAgKQ0KDQpkZl90ZXN0IDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nocm9tZV9wcmUgJT4lDQogIHNlbGVjdCgNCiAgICByZWdpb25fdjIsIGNvdW50cnksIGNoYW5uZWwsIHRhY3RpYywNCiAgICBjb3N0X3NwZW50X29uX2V4cG9zZWRfZ3JvdXA6YWJzb2x1dGVfbGlmdA0KICApDQoNCmlzb19jaHJvbWUgPC0gaXNvbGF0aW9uRm9yZXN0JG5ldyhzYW1wbGVfc2l6ZSA9IG5yb3coZGZfdGVzdCksIG51bV90cmVlcyA9IDEwMDAwLCBzZWVkID0gMTE1MykNCg0KaXNvX2Nocm9tZSRmaXQoZGZfdGVzdCkNCg0Kc2NvcmVzX3RyYWluIDwtIGRmX3Rlc3QgJT4lDQogIGlzb19jaHJvbWUkcHJlZGljdCgpICU+JQ0KICBhcnJhbmdlKGRlc2MoYW5vbWFseV9zY29yZSkpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nocm9tZV9wcmUyIDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nocm9tZV9wcmUgJT4lDQogIGxlZnRfam9pbihzY29yZXNfdHJhaW4sIGJ5ID0gYygiaWQyIiA9ICJpZCIpKSAlPiUgDQogIGZpbHRlcihhdmVyYWdlX2RlcHRoID4gMykNCg0KDQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9jaHJvbWUgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfY2hyb21lX3ByZTIgJT4lDQogIG5hbWVkX2dyb3VwX3NwbGl0KHRhY3RpYykNCmBgYA0KDQojIyMjIFJ1biBNb2RlbA0KDQpgYGB7ciwgd2FybmluZyA9IGZhbHNlfQ0KDQoNCmZpdHNfbm9uX3NlYXJjaF9jaHJvbWUgPC0gbW9kZWxfd3JhcHBlcl9mdW5jdGlvbihkZiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nocm9tZSxwb2x5X2luZCA9IDApDQoNCmJlc3RfaW5kX25vbl9zZWFyY2hfY2hyb21lIDwtIA0KICBsYXBwbHkoMTpsZW5ndGgoRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfY2hyb21lKSwgYmVzdF9pbmRfZnVuY3Rpb24sZGYgPSBmaXRzX25vbl9zZWFyY2hfY2hyb21lLA0KICAgICAgICAgZGYyID0gRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfY2hyb21lKSANCg0KY29lZl9ub25fc2VhcmNoX2Nocm9tZSA8LSBiZXN0X2luZF9ub25fc2VhcmNoX2Nocm9tZSAlPiUgYmluZF9yb3dzICNtYWtlIGEgbWF0cml4IG9mIGFsbCBjb2Vmcw0KDQpiZXN0X2ZpdF9ub25fc2VhcmNoX2Nocm9tZSA8LSBiZXN0X2luZF9ub25fc2VhcmNoX2Nocm9tZSAlPiUNCiAgc2V0X25hbWVzKG5hbWVzX2Z1bmN0aW9uKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nocm9tZV9wcmUsIHRhY3RpYykpICANCmBgYA0KDQojIyMjIENyZWF0ZSBHcmFwaCBPYmplY3QNCg0KYGBge3J9DQpncmFwaF9saXN0X2Nocm9tZSA8LSBsYXBwbHkoMTpsZW5ndGgoYmVzdF9maXRfbm9uX3NlYXJjaF9jaHJvbWUpLCBncmFwaGluZ19mdW5jdGlvbjQsIGRmMSA9IGJlc3RfZml0X25vbl9zZWFyY2hfY2hyb21lLCBkZjIgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9jaHJvbWUpDQpgYGANCg0KYGBge3J9DQplbmRfdGltZSA8LSBTeXMudGltZSgpDQoNCnRpbWVfY2hyb21lID0gZW5kX3RpbWUgLSBzdGFydF90aW1lDQoNCnRpbWVfY2hyb21lDQpgYGANCg0KIyMjIENsb3VkDQoNCiMjIyMgRGF0YSBSZWFkaW4NCg0KYGBge3J9DQpzdGFydF90aW1lIDwtIFN5cy50aW1lKCkNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfY2xvdWRfcHJlIDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlICU+JQ0KICBmaWx0ZXIocGEgJWluJSBjKCJDbG91ZCBHQ1AiLCAiQ2xvdWQgV29ya3NwYWNlIikpICU+JQ0KICBtdXRhdGUoDQogICAgcGEgPSAiQ2xvdWQiLA0KICAgIHBhMiA9ICJDbG91ZCAtIEFsbCBDaGFubmVsIg0KICApICU+JQ0KICBtdXRhdGUoDQogICAgaWQyID0gcm93X251bWJlcigpDQogICkNCg0KZGZfdGVzdCA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9jbG91ZF9wcmUgJT4lDQogICMgc2VsZWN0KC1zdHVkeV9pZCwgLWlkMiwgLXJlZ2lvbiwgLXNjYWxpbmdfZmFjdG9yLCAtcXVhcnRlciwgLXBhLCAtc3R1ZHlfbmFtZSkNCiAgc2VsZWN0KA0KICAgIHJlZ2lvbl92MiwgY291bnRyeSwgY2hhbm5lbCwgdGFjdGljLA0KICAgICMgdHJlYXRtZW50X3VzZXJfY291bnQ6Y29udHJvbCwNCiAgICBjb3N0X3NwZW50X29uX2V4cG9zZWRfZ3JvdXA6YWJzb2x1dGVfbGlmdCwgcGFyc2VkX3R5cGUNCiAgKQ0KDQppc29fY2xvdWQgPC0gaXNvbGF0aW9uRm9yZXN0JG5ldyhzYW1wbGVfc2l6ZSA9IG5yb3coZGZfdGVzdCksIG51bV90cmVlcyA9IDEwMDAwLCBzZWVkID0gMTE1MykNCg0KaXNvX2Nsb3VkJGZpdChkZl90ZXN0KQ0KDQpzY29yZXNfdHJhaW4gPC0gZGZfdGVzdCAlPiUNCiAgaXNvX2Nsb3VkJHByZWRpY3QoKSAlPiUNCiAgYXJyYW5nZShkZXNjKGFub21hbHlfc2NvcmUpKQ0KDQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9jbG91ZF9wcmUyIDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nsb3VkX3ByZSAlPiUNCiAgbGVmdF9qb2luKHNjb3Jlc190cmFpbiwgYnkgPSBjKCJpZDIiID0gImlkIikpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nsb3VkIDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nsb3VkX3ByZTIgJT4lDQogIG5hbWVkX2dyb3VwX3NwbGl0KHBhMikNCg0KYGBgDQoNCiMjIyMgUnVuIE1vZGVsDQoNCmBgYHtyLCB3YXJuaW5nID0gZmFsc2V9DQpmaXRzX25vbl9zZWFyY2hfY2xvdWQgPC0gbW9kZWxfd3JhcHBlcl9mdW5jdGlvbihkZiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nsb3VkLHBvbHlfaW5kID0gMCkNCg0KYmVzdF9pbmRfbm9uX3NlYXJjaF9jbG91ZCA8LSANCiAgbGFwcGx5KDE6bGVuZ3RoKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nsb3VkKSwgYmVzdF9pbmRfZnVuY3Rpb24sZGYgPSBmaXRzX25vbl9zZWFyY2hfY2xvdWQsDQogICAgICAgICBkZjIgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9jbG91ZCkgDQoNCmNvZWZfbm9uX3NlYXJjaF9jbG91ZCA8LSBiZXN0X2luZF9ub25fc2VhcmNoX2Nsb3VkICU+JSBiaW5kX3Jvd3MgI21ha2UgYSBtYXRyaXggb2YgYWxsIGNvZWZzDQoNCmJlc3RfZml0X25vbl9zZWFyY2hfY2xvdWQgPC0gYmVzdF9pbmRfbm9uX3NlYXJjaF9jbG91ZCAlPiUNCiAgc2V0X25hbWVzKG5hbWVzX2Z1bmN0aW9uKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nsb3VkX3ByZSwgcGEyKSkgIA0KYGBgDQoNCiMjIyMgQ3JlYXRlIEdyYXBoIE9iamVjdA0KDQpgYGB7cn0NCmdyYXBoX2xpc3RfY2xvdWQgPC0gbGFwcGx5KDE6bGVuZ3RoKGJlc3RfZml0X25vbl9zZWFyY2hfY2xvdWQpLCBncmFwaGluZ19mdW5jdGlvbjQsIGRmMSA9IGJlc3RfZml0X25vbl9zZWFyY2hfY2xvdWQsIGRmMiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2Nsb3VkKQ0KYGBgDQoNCg0KYGBge3J9DQplbmRfdGltZSA8LSBTeXMudGltZSgpDQoNCnRpbWVfY2xvdWQgPSBlbmRfdGltZSAtIHN0YXJ0X3RpbWUNCmBgYA0KDQojIyMgWW91VHViZQ0KDQojIyMjIERhdGEgUmVhZGluDQoNCmBgYHtyfQ0KDQpzdGFydF90aW1lIDwtIFN5cy50aW1lKCkNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfeW91dHViZV9wcmUgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGUgJT4lDQogIGZpbHRlcihwYSAlaW4lIGMoIllvdVR1YmUgVFYiLCAiWVRNUCIpKSAlPiUNCiAgbXV0YXRlKA0KICAgIHBhID0gIllvdVR1YmUiLA0KICAgIHBhMiA9ICJZb3VUdWJlIg0KICApICU+JQ0KICAjICBmaWx0ZXIoYWJzb2x1dGVfbGlmdCA8IDUwMDApICU+JQ0KICBtdXRhdGUoDQogICAgaWQyID0gcm93X251bWJlcigpDQogICkNCg0KZGZfdGVzdCA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV95b3V0dWJlX3ByZSAlPiUNCiAgIyBzZWxlY3QoLXN0dWR5X2lkLCAtaWQyLCAtcmVnaW9uLCAtc2NhbGluZ19mYWN0b3IsIC1xdWFydGVyLCAtcGEsIC1zdHVkeV9uYW1lKQ0KICBzZWxlY3QoDQogICAgcmVnaW9uX3YyLCBjb3VudHJ5LCBjaGFubmVsLCB0YWN0aWMsDQogICAgIyB0cmVhdG1lbnRfdXNlcl9jb3VudDpjb250cm9sLA0KICAgIGNvc3Rfc3BlbnRfb25fZXhwb3NlZF9ncm91cDphYnNvbHV0ZV9saWZ0LCBwYXJzZWRfdHlwZQ0KICApDQoNCmlzb195dCA8LSBpc29sYXRpb25Gb3Jlc3QkbmV3KHNhbXBsZV9zaXplID0gbnJvdyhkZl90ZXN0KSwgbnVtX3RyZWVzID0gMTAwMDAsIHNlZWQgPSAxMTUzKQ0KDQppc29feXQkZml0KGRmX3Rlc3QpDQoNCnNjb3Jlc190cmFpbiA8LSBkZl90ZXN0ICU+JQ0KICBpc29feXQkcHJlZGljdCgpICU+JQ0KICBhcnJhbmdlKGRlc2MoYW5vbWFseV9zY29yZSkpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3lvdXR1YmVfcHJlMiA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV95b3V0dWJlX3ByZSAlPiUNCiAgbGVmdF9qb2luKHNjb3Jlc190cmFpbiwgYnkgPSBjKCJpZDIiID0gImlkIikpICU+JQ0KICBmaWx0ZXIoYXZlcmFnZV9kZXB0aCA+IDMuODkpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3lvdXR1YmUgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfeW91dHViZV9wcmUyICU+JQ0KICBuYW1lZF9ncm91cF9zcGxpdChyZWdpb25fdjIpDQpgYGANCg0KIyMjIyBSdW4gTW9kZWwNCg0KYGBge3IsIHdhcm5pbmcgPSBmYWxzZX0NCmZpdHNfbm9uX3NlYXJjaF95b3V0dWJlIDwtIG1vZGVsX3dyYXBwZXJfZnVuY3Rpb24oZGYgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV95b3V0dWJlLHBvbHlfaW5kID0gMCkNCg0KYmVzdF9pbmRfbm9uX3NlYXJjaF95b3V0dWJlIDwtIA0KICBsYXBwbHkoMTpsZW5ndGgoRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfeW91dHViZSksIGJlc3RfaW5kX2Z1bmN0aW9uLGRmID0gZml0c19ub25fc2VhcmNoX3lvdXR1YmUsDQogICAgICAgICBkZjIgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV95b3V0dWJlKSANCg0KY29lZl9ub25fc2VhcmNoX3lvdXR1YmUgPC0gYmVzdF9pbmRfbm9uX3NlYXJjaF95b3V0dWJlICU+JSBiaW5kX3Jvd3MgI21ha2UgYSBtYXRyaXggb2YgYWxsIGNvZWZzDQoNCmJlc3RfZml0X25vbl9zZWFyY2hfeW91dHViZSA8LSBiZXN0X2luZF9ub25fc2VhcmNoX3lvdXR1YmUgJT4lDQogIHNldF9uYW1lcyhuYW1lc19mdW5jdGlvbihGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV95b3V0dWJlX3ByZSwgcGEyKSkgIA0KYGBgDQoNCiMjIyMgQ3JlYXRlIEdyYXBoIE9iamVjdA0KDQpgYGB7cn0NCmdyYXBoX2xpc3RfeW91dHViZSA8LSBsYXBwbHkoMTpsZW5ndGgoYmVzdF9maXRfbm9uX3NlYXJjaF95b3V0dWJlKSwgZ3JhcGhpbmdfZnVuY3Rpb240LCBkZjEgPSBiZXN0X2ZpdF9ub25fc2VhcmNoX3lvdXR1YmUsIGRmMiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3lvdXR1YmUpDQpgYGANCg0KDQpgYGB7cn0NCmVuZF90aW1lIDwtIFN5cy50aW1lKCkNCg0KdGltZV95b3V0dWJlID0gZW5kX3RpbWUgLSBzdGFydF90aW1lDQpgYGANCg0KDQojIyMgRFNNDQoNCiMjIyMgRGF0YSBSZWFkaW4NCg0KYGBge3J9DQoNCnN0YXJ0X3RpbWUgPC0gU3lzLnRpbWUoKQ0KDQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9kc21fcHJlIDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlICU+JQ0KICBmaWx0ZXIocGEgPT0gIkRTTSIpICU+JQ0KICBmaWx0ZXIocmVnaW9uX3YyICE9ICJBUEFDIikgJT4lDQogICMgZmlsdGVyKGFic29sdXRlX2xpZnQgPCAxMDAwKSAjICU+JQ0KICAjIGZpbHRlcihzdHVkeV9pZCAhPSAnNjI5NzQyMCcpICMlPiUNCiAgIyAgZmlsdGVyKHN0dWR5X2lkICE9JzE0OTE2MTcxMScpICU+JQ0KICAjICBmaWx0ZXIoc3R1ZHlfaWQgIT0gJzE0ODYxMzAwMicpICU+JQ0KICAjIGZpbHRlcihzdHVkeV9pZCAhPSczMjg0NjI1JykgJT4lDQogICMgIGZpbHRlcihzdHVkeV9pZCAhPSczMzI5MTMxJykNCiAgbXV0YXRlKA0KICAgIGlkMiA9IHJvd19udW1iZXIoKQ0KICApDQoNCmRmX3Rlc3QgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX3ByZSAlPiUNCiAgIyBzZWxlY3QoLXN0dWR5X2lkLCAtaWQyLCAtcmVnaW9uLCAtc2NhbGluZ19mYWN0b3IsIC1xdWFydGVyLCAtcGEsIC1zdHVkeV9uYW1lKQ0KICBzZWxlY3QoDQogICAgcmVnaW9uX3YyLCBjb3VudHJ5LCBjaGFubmVsLCB0YWN0aWMsDQogICAgIyB0cmVhdG1lbnRfdXNlcl9jb3VudDpjb250cm9sLA0KICAgIGNvc3Rfc3BlbnRfb25fZXhwb3NlZF9ncm91cDphYnNvbHV0ZV9saWZ0DQogICkNCg0KaXNvX2RzbSA8LSBpc29sYXRpb25Gb3Jlc3QkbmV3KHNhbXBsZV9zaXplID0gbnJvdyhkZl90ZXN0KSwgbnVtX3RyZWVzID0gMTAwMDAsIHNlZWQgPSAxMTUyKQ0KDQppc29fZHNtJGZpdChkZl90ZXN0KQ0KDQpzY29yZXNfdHJhaW4gPC0gZGZfdGVzdCAlPiUNCiAgaXNvX2RzbSRwcmVkaWN0KCkgJT4lDQogIGFycmFuZ2UoZGVzYyhhbm9tYWx5X3Njb3JlKSkNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX3ByZTIgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX3ByZSAlPiUNCiAgbGVmdF9qb2luKHNjb3Jlc190cmFpbiwgYnkgPSBjKCJpZDIiID0gImlkIikpICU+JQ0KICBmaWx0ZXIoYXZlcmFnZV9kZXB0aCA+IDUpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbSA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9kc21fcHJlMiAlPiUNCiAgbmFtZWRfZ3JvdXBfc3BsaXQocmVnaW9uX3YyLCBjaGFubmVsKQ0KYGBgDQoNCiMjIyMgUnVuIE1vZGVsDQoNCmBgYHtyLCB3YXJuaW5nID0gZmFsc2V9DQpmaXRzX25vbl9zZWFyY2hfZHNtIDwtIG1vZGVsX3dyYXBwZXJfZnVuY3Rpb24oZGYgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9kc20scG9seV9pbmQgPSAwKQ0KDQpiZXN0X2luZF9ub25fc2VhcmNoX2RzbSA8LSANCiAgbGFwcGx5KDE6bGVuZ3RoKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbSksIGJlc3RfaW5kX2Z1bmN0aW9uLGRmID0gZml0c19ub25fc2VhcmNoX2RzbSwNCiAgICAgICAgIGRmMiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbSkNCg0KY29lZl9ub25fc2VhcmNoX2RzbSA8LSBiZXN0X2luZF9ub25fc2VhcmNoX2RzbSAlPiUgYmluZF9yb3dzICNtYWtlIGEgbWF0cml4IG9mIGFsbCBjb2Vmcw0KDQpiZXN0X2ZpdF9ub25fc2VhcmNoX2RzbSA8LSBiZXN0X2luZF9ub25fc2VhcmNoX2RzbSAlPiUNCiAgc2V0X25hbWVzKG5hbWVzX2Z1bmN0aW9uKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbV9wcmUsIHJlZ2lvbl92MixjaGFubmVsKSkgIA0KYGBgDQoNCiMjIyMgQ3JlYXRlIEdyYXBoIE9iamVjdA0KDQpgYGB7cn0NCmdyYXBoX2xpc3RfZHNtIDwtIGxhcHBseSgxOmxlbmd0aChiZXN0X2ZpdF9ub25fc2VhcmNoX2RzbSksIGdyYXBoaW5nX2Z1bmN0aW9uNCwgZGYxID0gYmVzdF9maXRfbm9uX3NlYXJjaF9kc20sIGRmMiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbSkNCmBgYA0KDQoNCmBgYHtyfQ0KZW5kX3RpbWUgPC0gU3lzLnRpbWUoKQ0KDQp0aW1lX2RzbSA9IGVuZF90aW1lIC0gc3RhcnRfdGltZQ0KYGBgDQoNCg0KIyMjIFBpeGVsDQoNCiMjIyMgRGF0YSBSZWFkaW4NCg0KYGBge3J9DQoNCnN0YXJ0X3RpbWUgPC0gU3lzLnRpbWUoKQ0KDQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9waXhlbF9wcmUgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGUgJT4lDQogIGZpbHRlcihwYSA9PSAiUGl4ZWwiKSAlPiUNCiAgbXV0YXRlKA0KICAgIHBhMiA9ICJQaXhlbCAtIEFsbCBDaGFubmVsIg0KICApICU+JQ0KICAjICAgZmlsdGVyKGFic29sdXRlX2xpZnQgPCAxMDAwKSAgJT4lDQogICMgZmlsdGVyKHN0dWR5X2lkICE9ICc2Mjk3NDIwJykgIyU+JQ0KICAjICBmaWx0ZXIoc3R1ZHlfaWQgIT0nMTQ5MTYxNzExJykgJT4lDQogICMgIGZpbHRlcihzdHVkeV9pZCAhPSAnMTQ4NjEzMDAyJykgJT4lDQogICMgZmlsdGVyKHN0dWR5X2lkICE9JzMyODQ2MjUnKSAlPiUNCiAgIyAgZmlsdGVyKHN0dWR5X2lkICE9JzMzMjkxMzEnKQ0KICBtdXRhdGUoDQogICAgaWQyID0gcm93X251bWJlcigpDQogICkNCg0KZGZfdGVzdCA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9waXhlbF9wcmUgJT4lDQogICMgc2VsZWN0KC1zdHVkeV9pZCwgLWlkMiwgLXJlZ2lvbiwgLXNjYWxpbmdfZmFjdG9yLCAtcXVhcnRlciwgLXBhLCAtc3R1ZHlfbmFtZSkNCiAgc2VsZWN0KA0KICAgIHJlZ2lvbl92MiwgY291bnRyeSwgY2hhbm5lbCwgdGFjdGljLA0KICAgICMgdHJlYXRtZW50X3VzZXJfY291bnQ6Y29udHJvbCwNCiAgICBjb3N0X3NwZW50X29uX2V4cG9zZWRfZ3JvdXA6YWJzb2x1dGVfbGlmdA0KICApDQoNCmlzb19waXhlbCA8LSBpc29sYXRpb25Gb3Jlc3QkbmV3KHNhbXBsZV9zaXplID0gbnJvdyhkZl90ZXN0KSwgbnVtX3RyZWVzID0gMTAwMDAsIHNlZWQgPSAxMTUyKQ0KDQppc29fcGl4ZWwkZml0KGRmX3Rlc3QpDQoNCnNjb3Jlc190cmFpbiA8LSBkZl90ZXN0ICU+JQ0KICBpc29fcGl4ZWwkcHJlZGljdCgpICU+JQ0KICBhcnJhbmdlKGRlc2MoYW5vbWFseV9zY29yZSkpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3BpeGVsX3ByZTIgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfcGl4ZWxfcHJlICU+JQ0KICBsZWZ0X2pvaW4oc2NvcmVzX3RyYWluLCBieSA9IGMoImlkMiIgPSAiaWQiKSkgJT4lDQogIGZpbHRlcihhdmVyYWdlX2RlcHRoID4gMy4xKQ0KDQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9waXhlbF9wcmUyDQoNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfcGl4ZWwgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfcGl4ZWxfcHJlMiAlPiUNCiAgbmFtZWRfZ3JvdXBfc3BsaXQocGEyKQ0KYGBgDQoNCiMjIyMgUnVuIE1vZGVsDQoNCmBgYHtyLCB3YXJuaW5nID0gZmFsc2V9DQpmaXRzX25vbl9zZWFyY2hfcGl4ZWwgPC0gbW9kZWxfd3JhcHBlcl9mdW5jdGlvbihkZiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3BpeGVsLHBvbHlfaW5kID0gMCkNCg0KYmVzdF9pbmRfbm9uX3NlYXJjaF9waXhlbCA8LSANCiAgbGFwcGx5KDE6bGVuZ3RoKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3BpeGVsKSwgYmVzdF9pbmRfZnVuY3Rpb24sZGYgPSBmaXRzX25vbl9zZWFyY2hfcGl4ZWwsDQogICAgICAgICBkZjIgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9waXhlbCkgDQoNCmNvZWZfbm9uX3NlYXJjaF9waXhlbCA8LSBiZXN0X2luZF9ub25fc2VhcmNoX3BpeGVsICU+JSBiaW5kX3Jvd3MgI21ha2UgYSBtYXRyaXggb2YgYWxsIGNvZWZzDQoNCmJlc3RfZml0X25vbl9zZWFyY2hfcGl4ZWwgPC0gYmVzdF9pbmRfbm9uX3NlYXJjaF9waXhlbCAlPiUNCiAgc2V0X25hbWVzKG5hbWVzX2Z1bmN0aW9uKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3BpeGVsX3ByZSwgcGEyKSkgIA0KYGBgDQoNCiMjIyMgQ3JlYXRlIEdyYXBoIE9iamVjdA0KDQpgYGB7cn0NCmdyYXBoX2xpc3RfcGl4ZWwgPC0gbGFwcGx5KDE6bGVuZ3RoKGJlc3RfZml0X25vbl9zZWFyY2hfcGl4ZWwpLCBncmFwaGluZ19mdW5jdGlvbjQsIGRmMSA9IGJlc3RfZml0X25vbl9zZWFyY2hfcGl4ZWwsIGRmMiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3BpeGVsKQ0KYGBgDQoNCg0KYGBge3J9DQplbmRfdGltZSA8LSBTeXMudGltZSgpDQoNCnRpbWVfcGl4ZWwgPSBlbmRfdGltZSAtIHN0YXJ0X3RpbWUNCmBgYA0KDQoNCiMjIyBGaQ0KDQojIyMjIERhdGEgUmVhZGluDQoNCmBgYHtyfQ0KDQpzdGFydF90aW1lIDwtIFN5cy50aW1lKCkNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZmlfcHJlIDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlICU+JQ0KICBmaWx0ZXIocGEgPT0gIkdvb2dsZSBGaSIpICU+JQ0KICBtdXRhdGUoDQogICAgcGEyID0gIkZpIC0gQWxsIENoYW5uZWwiDQogICkgJT4lDQogICMgICBmaWx0ZXIoYWJzb2x1dGVfbGlmdCA8IDEwMDApICAlPiUNCiAgIyBmaWx0ZXIoc3R1ZHlfaWQgIT0gJzYyOTc0MjAnKSAjJT4lDQogICMgIGZpbHRlcihzdHVkeV9pZCAhPScxNDkxNjE3MTEnKSAlPiUNCiAgIyAgZmlsdGVyKHN0dWR5X2lkICE9ICcxNDg2MTMwMDInKSAlPiUNCiAgIyBmaWx0ZXIoc3R1ZHlfaWQgIT0nMzI4NDYyNScpICU+JQ0KICAjICBmaWx0ZXIoc3R1ZHlfaWQgIT0nMzMyOTEzMScpDQogIG11dGF0ZSgNCiAgICBpZDIgPSByb3dfbnVtYmVyKCkNCiAgKQ0KDQpkZl90ZXN0IDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2ZpX3ByZSAlPiUNCiAgIyBzZWxlY3QoLXN0dWR5X2lkLCAtaWQyLCAtcmVnaW9uLCAtc2NhbGluZ19mYWN0b3IsIC1xdWFydGVyLCAtcGEsIC1zdHVkeV9uYW1lKQ0KICBzZWxlY3QoDQogICAgcmVnaW9uX3YyLCBjb3VudHJ5LCBjaGFubmVsLCB0YWN0aWMsDQogICAgIyB0cmVhdG1lbnRfdXNlcl9jb3VudDpjb250cm9sLA0KICAgIGNvc3Rfc3BlbnRfb25fZXhwb3NlZF9ncm91cDphYnNvbHV0ZV9saWZ0DQogICkNCg0KaXNvX2ZpIDwtIGlzb2xhdGlvbkZvcmVzdCRuZXcoc2FtcGxlX3NpemUgPSBucm93KGRmX3Rlc3QpLCBudW1fdHJlZXMgPSAxMDAwMCwgc2VlZCA9IDExNTIpDQoNCmlzb19maSRmaXQoZGZfdGVzdCkNCg0Kc2NvcmVzX3RyYWluIDwtIGRmX3Rlc3QgJT4lDQogIGlzb19maSRwcmVkaWN0KCkgJT4lDQogIGFycmFuZ2UoZGVzYyhhbm9tYWx5X3Njb3JlKSkNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZmlfcHJlMiA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9maV9wcmUgJT4lDQogIGxlZnRfam9pbihzY29yZXNfdHJhaW4sIGJ5ID0gYygiaWQyIiA9ICJpZCIpKSAlPiUNCiAgZmlsdGVyKGF2ZXJhZ2VfZGVwdGggPiA0Ljc1KQ0KDQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9maV9wcmUyDQoNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZmkgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZmlfcHJlMiAlPiUNCiAgbmFtZWRfZ3JvdXBfc3BsaXQoY2hhbm5lbCkNCmBgYA0KDQojIyMjIFJ1biBNb2RlbA0KDQpgYGB7ciwgd2FybmluZyA9IGZhbHNlfQ0KZml0c19ub25fc2VhcmNoX2ZpIDwtIG1vZGVsX3dyYXBwZXJfZnVuY3Rpb24oZGYgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9maSxwb2x5X2luZCA9IDApDQoNCmJlc3RfaW5kX25vbl9zZWFyY2hfZmkgPC0gDQogIGxhcHBseSgxOmxlbmd0aChGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9maSksIGJlc3RfaW5kX2Z1bmN0aW9uLGRmID0gZml0c19ub25fc2VhcmNoX2ZpLA0KICAgICAgICAgZGYyID0gRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZmkpIA0KDQpjb2VmX25vbl9zZWFyY2hfZmkgPC0gYmVzdF9pbmRfbm9uX3NlYXJjaF9maSAlPiUgYmluZF9yb3dzICNtYWtlIGEgbWF0cml4IG9mIGFsbCBjb2Vmcw0KDQpiZXN0X2ZpdF9ub25fc2VhcmNoX2ZpIDwtIGJlc3RfaW5kX25vbl9zZWFyY2hfZmkgJT4lDQogIHNldF9uYW1lcyhuYW1lc19mdW5jdGlvbihGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9maV9wcmUsIHBhMikpICANCmBgYA0KDQojIyMjIENyZWF0ZSBHcmFwaCBPYmplY3QNCg0KYGBge3J9DQpncmFwaF9saXN0X2ZpIDwtIGxhcHBseSgxOmxlbmd0aChiZXN0X2ZpdF9ub25fc2VhcmNoX2ZpKSwgZ3JhcGhpbmdfZnVuY3Rpb240LCBkZjEgPSBiZXN0X2ZpdF9ub25fc2VhcmNoX2ZpLCBkZjIgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9maSkNCmBgYA0KDQoNCmBgYHtyfQ0KZW5kX3RpbWUgPC0gU3lzLnRpbWUoKQ0KDQp0aW1lX2ZpID0gZW5kX3RpbWUgLSBzdGFydF90aW1lDQpgYGANCg0KDQojIyMgU01CIC0gUUxlYWRzDQoNCiMjIyMgRGF0YSBSZWFkaW4NCg0KYGBge3J9DQoNCnN0YXJ0X3RpbWUgPC0gU3lzLnRpbWUoKQ0KDQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9zbWJxX3ByZSA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZSAlPiUNCiAgZmlsdGVyKGdyb3VwZWRfY29udmVyc2lvbiA9PSAnTGVuYSBRIExlYWQnKSAlPiUNCiAgbXV0YXRlKA0KICAgIHBhMiA9ICJTTUIgLSBRLUxlYWQiDQogICkgJT4lDQogICMgICBmaWx0ZXIoYWJzb2x1dGVfbGlmdCA8IDEwMDApICAlPiUNCiAgIyBmaWx0ZXIoc3R1ZHlfaWQgIT0gJzYyOTc0MjAnKSAjJT4lDQogICMgIGZpbHRlcihzdHVkeV9pZCAhPScxNDkxNjE3MTEnKSAlPiUNCiAgIyAgZmlsdGVyKHN0dWR5X2lkICE9ICcxNDg2MTMwMDInKSAlPiUNCiAgIyBmaWx0ZXIoc3R1ZHlfaWQgIT0nMzI4NDYyNScpICU+JQ0KICAjICBmaWx0ZXIoc3R1ZHlfaWQgIT0nMzMyOTEzMScpDQogIG11dGF0ZSgNCiAgICBpZDIgPSByb3dfbnVtYmVyKCkNCiAgKQ0KDQpkZl90ZXN0IDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3NtYnFfcHJlICU+JQ0KICAjIHNlbGVjdCgtc3R1ZHlfaWQsIC1pZDIsIC1yZWdpb24sIC1zY2FsaW5nX2ZhY3RvciwgLXF1YXJ0ZXIsIC1wYSwgLXN0dWR5X25hbWUpDQogIHNlbGVjdCgNCiAgICByZWdpb25fdjIsIGNvdW50cnksIGNoYW5uZWwsIHRhY3RpYywNCiAgICAjIHRyZWF0bWVudF91c2VyX2NvdW50OmNvbnRyb2wsDQogICAgY29zdF9zcGVudF9vbl9leHBvc2VkX2dyb3VwOmFic29sdXRlX2xpZnQNCiAgKQ0KDQppc29fc21icSA8LSBpc29sYXRpb25Gb3Jlc3QkbmV3KHNhbXBsZV9zaXplID0gbnJvdyhkZl90ZXN0KSwgbnVtX3RyZWVzID0gMTAwMDAsIHNlZWQgPSAxMTUyKQ0KDQppc29fc21icSRmaXQoZGZfdGVzdCkNCg0Kc2NvcmVzX3RyYWluIDwtIGRmX3Rlc3QgJT4lDQogIGlzb19zbWJxJHByZWRpY3QoKSAlPiUNCiAgYXJyYW5nZShkZXNjKGFub21hbHlfc2NvcmUpKQ0KDQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9zbWJxX3ByZTIgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21icV9wcmUgJT4lDQogIGxlZnRfam9pbihzY29yZXNfdHJhaW4sIGJ5ID0gYygiaWQyIiA9ICJpZCIpKSAlPiUgDQogIGZpbHRlcihhdmVyYWdlX2RlcHRoID4gMSkNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21icSA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9zbWJxX3ByZTIgJT4lDQogIG5hbWVkX2dyb3VwX3NwbGl0KHBhMikNCmBgYA0KDQojIyMjIFJ1biBNb2RlbA0KDQpgYGB7ciwgd2FybmluZyA9IGZhbHNlfQ0KZml0c19ub25fc2VhcmNoX3NtYnEgPC0gbW9kZWxfd3JhcHBlcl9mdW5jdGlvbihkZiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3NtYnEscG9seV9pbmQgPSAwKQ0KDQpiZXN0X2luZF9ub25fc2VhcmNoX3NtYnEgPC0gDQogIGxhcHBseSgxOmxlbmd0aChGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9zbWJxKSwgYmVzdF9pbmRfZnVuY3Rpb24sZGYgPSBmaXRzX25vbl9zZWFyY2hfc21icSwNCiAgICAgICAgIGRmMiA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3NtYnEpIA0KDQpjb2VmX25vbl9zZWFyY2hfc21icSA8LSBiZXN0X2luZF9ub25fc2VhcmNoX3NtYnEgJT4lIGJpbmRfcm93cyAjbWFrZSBhIG1hdHJpeCBvZiBhbGwgY29lZnMNCg0KYmVzdF9maXRfbm9uX3NlYXJjaF9zbWJxIDwtIGJlc3RfaW5kX25vbl9zZWFyY2hfc21icSAlPiUNCiAgc2V0X25hbWVzKG5hbWVzX2Z1bmN0aW9uKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3NtYnFfcHJlLCBwYTIpKSAgDQpgYGANCg0KIyMjIyBDcmVhdGUgR3JhcGggT2JqZWN0DQoNCmBgYHtyfQ0KZ3JhcGhfbGlzdF9zbWJxIDwtIGxhcHBseSgxOmxlbmd0aChiZXN0X2ZpdF9ub25fc2VhcmNoX3NtYnEpLCBncmFwaGluZ19mdW5jdGlvbjQsIGRmMSA9IGJlc3RfZml0X25vbl9zZWFyY2hfc21icSwgZGYyID0gRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21icSkNCmBgYA0KDQoNCmBgYHtyfQ0KZW5kX3RpbWUgPC0gU3lzLnRpbWUoKQ0KDQp0aW1lX3NtYnEgPSBlbmRfdGltZSAtIHN0YXJ0X3RpbWUNCmBgYA0KDQoNCiMjIyBTTUIgLSBCTGVhZHMNCg0KIyMjIyBEYXRhIFJlYWRpbg0KDQpgYGB7cn0NCg0Kc3RhcnRfdGltZSA8LSBTeXMudGltZSgpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3NtYmJfcHJlIDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlICU+JQ0KICBmaWx0ZXIocGEgPT0gIlNNQiIgJiBncm91cGVkX2NvbnZlcnNpb24gPT0gJ0xlbmEgQiBMZWFkJykgJT4lDQogIG11dGF0ZSgNCiAgICBwYTIgPSAiU01CIC0gQi1MZWFkIg0KICApICU+JQ0KICAjICAgZmlsdGVyKGFic29sdXRlX2xpZnQgPCAxMDAwKSAgJT4lDQogICMgZmlsdGVyKHN0dWR5X2lkICE9ICc2Mjk3NDIwJykgIyU+JQ0KICAjICBmaWx0ZXIoc3R1ZHlfaWQgIT0nMTQ5MTYxNzExJykgJT4lDQogICMgIGZpbHRlcihzdHVkeV9pZCAhPSAnMTQ4NjEzMDAyJykgJT4lDQogICMgZmlsdGVyKHN0dWR5X2lkICE9JzMyODQ2MjUnKSAlPiUNCiAgIyAgZmlsdGVyKHN0dWR5X2lkICE9JzMzMjkxMzEnKQ0KICBtdXRhdGUoDQogICAgaWQyID0gcm93X251bWJlcigpDQogICkNCg0KZGZfdGVzdCA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9zbWJiX3ByZSAlPiUNCiAgIyBzZWxlY3QoLXN0dWR5X2lkLCAtaWQyLCAtcmVnaW9uLCAtc2NhbGluZ19mYWN0b3IsIC1xdWFydGVyLCAtcGEsIC1zdHVkeV9uYW1lKQ0KICBzZWxlY3QoDQogICAgcmVnaW9uX3YyLCBjb3VudHJ5LCBjaGFubmVsLCB0YWN0aWMsDQogICAgIyB0cmVhdG1lbnRfdXNlcl9jb3VudDpjb250cm9sLA0KICAgIGNvc3Rfc3BlbnRfb25fZXhwb3NlZF9ncm91cDphYnNvbHV0ZV9saWZ0DQogICkNCg0KaXNvX3NtYmIgPC0gaXNvbGF0aW9uRm9yZXN0JG5ldyhzYW1wbGVfc2l6ZSA9IG5yb3coZGZfdGVzdCksIG51bV90cmVlcyA9IDEwMDAwLCBzZWVkID0gMTE1MikNCg0KaXNvX3NtYmIkZml0KGRmX3Rlc3QpDQoNCnNjb3Jlc190cmFpbiA8LSBkZl90ZXN0ICU+JQ0KICBpc29fc21iYiRwcmVkaWN0KCkgJT4lDQogIGFycmFuZ2UoZGVzYyhhbm9tYWx5X3Njb3JlKSkNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21iYl9wcmUyIDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3NtYmJfcHJlICU+JQ0KICBsZWZ0X2pvaW4oc2NvcmVzX3RyYWluLCBieSA9IGMoImlkMiIgPSAiaWQiKSkgJT4lIA0KICBmaWx0ZXIoYXZlcmFnZV9kZXB0aCA+IDQpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3NtYmIgPC0NCiAgRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21iYl9wcmUyICU+JQ0KICBuYW1lZF9ncm91cF9zcGxpdChjaGFubmVsKQ0KYGBgDQoNCiMjIyMgUnVuIE1vZGVsDQoNCmBgYHtyLCB3YXJuaW5nID0gZmFsc2V9DQpmaXRzX25vbl9zZWFyY2hfc21iYiA8LSBtb2RlbF93cmFwcGVyX2Z1bmN0aW9uKGRmID0gRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21iYixwb2x5X2luZCA9IDApDQoNCmJlc3RfaW5kX25vbl9zZWFyY2hfc21iYiA8LSANCiAgbGFwcGx5KDE6bGVuZ3RoKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX3NtYmIpLCBiZXN0X2luZF9mdW5jdGlvbixkZiA9IGZpdHNfbm9uX3NlYXJjaF9zbWJiLA0KICAgICAgICAgZGYyID0gRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21iYikgDQoNCmNvZWZfbm9uX3NlYXJjaF9zbWJiIDwtIGJlc3RfaW5kX25vbl9zZWFyY2hfc21iYiAlPiUgYmluZF9yb3dzICNtYWtlIGEgbWF0cml4IG9mIGFsbCBjb2Vmcw0KDQpiZXN0X2ZpdF9ub25fc2VhcmNoX3NtYmIgPC0gYmVzdF9pbmRfbm9uX3NlYXJjaF9zbWJiICU+JQ0KICBzZXRfbmFtZXMobmFtZXNfZnVuY3Rpb24oRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21iYl9wcmUsIGNoYW5uZWwpKSAgDQpgYGANCg0KIyMjIyBDcmVhdGUgR3JhcGggT2JqZWN0DQoNCmBgYHtyfQ0KZ3JhcGhfbGlzdF9zbWJiIDwtIGxhcHBseSgxOmxlbmd0aChiZXN0X2ZpdF9ub25fc2VhcmNoX3NtYmIpLCBncmFwaGluZ19mdW5jdGlvbjQsIGRmMSA9IGJlc3RfZml0X25vbl9zZWFyY2hfc21iYiwgZGYyID0gRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfc21iYikNCmBgYA0KDQoNCmBgYHtyfQ0KZW5kX3RpbWUgPC0gU3lzLnRpbWUoKQ0KDQp0aW1lX3NtYmIgPSBlbmRfdGltZSAtIHN0YXJ0X3RpbWUNCmBgYA0KDQojIyBFeHBvcnQgYWxsIGdyYXBoIGxpc3RzDQoNCmBgYHtyfQ0KZ3JhcGhfbmFtZXMgPC0gbWdldChscyhwYXQgPSAnZ3JhcGhfbGlzdF8nKSkNCiAgIA0KZGZfbmFtZXMgPC0gbWdldChzZXRkaWZmKGxzKHBhdHRlcm4gPSAnRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfJyksIGxzKHBhdHRlcm4gPSAicHJlIikpKQ0KDQojcm0oRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfQ2hyb21lLEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX0Nsb3VkLEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX1lvdVR1YmUpDQoNCiNsYXBwbHkoMTpsZW5ndGgoZ3JhcGhfbmFtZXMpLA0KIyAgICAgIGZ1bmN0aW9uKGopIHsNCiNsYXBwbHkoMTpsZW5ndGgoZGZfbmFtZXNbW2pdXSksZXhwb3J0X3JwbG90c19mdW5jdGlvbjIsc3RhcnRpbmdfbmFtZSA9ICJOb25fU2VhcmNoXyIsZm9sZGVyX25hbWUgPSBmb2xkZXJfbmFtZSxkZl9saXN0ID0gI2RmX25hbWVzW1tqXV0sZ3JhcGhpbmdfbGlzdCA9IGdyYXBoX25hbWVzW2pdW1sxXV0pDQojICAgICAgfQ0KIyAgICAgICApDQpgYGANCg0KIyMgR3JpZCBvZiBhbGwgUmVzcG9uc2UgQ3VydmVzDQoNClsqU3ViIFBsb3QgRG9jdW1lbnRhdGlvbipdKGh0dHBzOi8vcGxvdGx5LmNvbS9yL3N1YnBsb3RzLykNCg0KYGBge3IsIGZpZy5oZWlnaHQ9IDE1LCBlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCg0KbGFwcGx5KDE6bGVuZ3RoKGdyYXBoX25hbWVzKSwNCmZ1bmN0aW9uKGkpew0KICBzdWJwbG90KGdyYXBoX25hbWVzW2ldW1sxXV0sIG5yb3dzID0gbGVuZ3RoKGdyYXBoX25hbWVzW2ldW1sxXV0pKQ0KfQ0KKQ0KDQoNCmxhcHBseSgxOmxlbmd0aChncmFwaF9uYW1lcyksDQpmdW5jdGlvbihpKXsNCiNwMSA9IGdyYXBoX25hbWVzW2ldW1sxXV0NCmRvLmNhbGwoZ3JpZC5hcnJhbmdlLGdyYXBoX25hbWVzW2ldW1sxXV0pDQojcmV0dXJuKGdyaWQuYXJyYW5nZShncm9icyA9IHAxKSkNCn0NCikNCg0KYGBgDQoNCiMjIENvZWYgTWF0cml4DQoNCmBgYHtyfQ0KY29lZi4yX21hdHJpeCA8LSBtZ2V0KChscyhwYXQgPSAnY29lZl8nKSkpICU+JSAgYmluZF9yb3dzKCkNCg0KY29lZi4yX21hdHJpeA0KDQoNCmBgYA0KDQojIyBHcmFwaHMgd2l0aCBBbm9tYWx5IFNjb3Jlcw0KDQpgYGB7cn0NCmdyYXBoX2xpc3QuZmkgPC0gbGFwcGx5KDE6bGVuZ3RoKGJlc3RfZml0X25vbl9zZWFyY2hfZmkpLCBncmFwaGluZ19mdW5jdGlvbjRfd19hbm9tLCBkZjEgPSBiZXN0X2ZpdF9ub25fc2VhcmNoX2ZpLCBkZjIgPSBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9maSkNCg0KIyMjIEFkZCBHRyBUZXh0IFJlcGVsDQpnZ3Bsb3RseShncmFwaF9saXN0LmZpW1szXV0pDQoNCmBgYA0KDQojIENyZWF0ZSBhbGwgUmVzcG9uc2UgQ3VydmVzIC0gUmlkZ2UvTGFzc28NCg0KYGBge3IsIHdhcm5pbmcgPSBGQUxTRX0NCg0Kc3RhcnRfdGltZSA8LSBTeXMudGltZSgpDQoNCmZpdHMubm9uLnNlYXJjaC5SSURHRV9MQVNTTyA8LSBsYXBwbHkoDQogIDE6bGVuZ3RoKGRmX25hbWVzKSwNCiAgZnVuY3Rpb24oaSkgew0KICAgIG1vZGVsX3dyYXBwZXJfZnVuY3Rpb24oZGYgPSBkZl9uYW1lc1tpXVtbMV1dLHBvbHlfaW5kID0gMCkNCiAgfQ0KKQ0KDQplbmRfdGltZSA8LSBTeXMudGltZSgpDQoNCmNvbWJpbmVkX3JpZGdlX3RpbWUgPC0gc3RhcnRfdGltZSAtIGVuZF90aW1lDQoNCmJlc3QuaW5kLm5vbi5zZWFyY2guUklER0VfTEFTU08gPC0gbGFwcGx5KA0KICAxOmxlbmd0aChkZl9uYW1lcyksDQogIGZ1bmN0aW9uKGkpIHsgICANCiAgbGFwcGx5KDE6bGVuZ3RoKGRmX25hbWVzW2ldW1sxXV0pLCBiZXN0X2luZF9mdW5jdGlvbixkZiA9IGZpdHMubm9uLnNlYXJjaC5SSURHRV9MQVNTT1tpXVtbMV1dLA0KICAgICAgICAgZGYyID0gZGZfbmFtZXNbaV1bWzFdXSkNCiAgfQ0KKQ0KDQpjb2VmLm5vbi5zZWFyY2guUklER0VfTEFTU08gPC0gbGFwcGx5KA0KICAxOmxlbmd0aChkZl9uYW1lcyksDQogIGZ1bmN0aW9uIChpKXsNCiAgYmVzdC5pbmQubm9uLnNlYXJjaC5SSURHRV9MQVNTT1tpXVtbMV1dICU+JSBiaW5kX3Jvd3MNCiAgfQ0KKSAlPiUNCiAgYmluZF9yb3dzKCkgJT4lIA0KICBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KIyAgbXV0YXRlKA0KIyAgICBjb3N0X3AyID0gMCwNCiMgICAgbGFtYmRhID0gMCwNCiMgICAgYWxwaGEgPSAwLA0KIyAgICBwb3dlcnMyID0gMA0KIyAgKSAlPiUgDQogIHNlbGVjdChvbmVfb2YoY29sbmFtZXMoY29lZi4yX21hdHJpeCkpKQ0KDQoNCmJlc3QuZml0Lm5vbi5zZWFyY2guUklER0VfTEFTU08gPC0gbGFwcGx5KDE6bGVuZ3RoKGRmX25hbWVzKSwNCiAgICAgIGZ1bmN0aW9uKGopIHsNCmxhcHBseSgxOmxlbmd0aChiZXN0LmluZC5ub24uc2VhcmNoLlJJREdFX0xBU1NPW1tqXV0pLA0KICAgICAgZnVuY3Rpb24oaSl7DQogICAgICAgIGJlc3QuaW5kLm5vbi5zZWFyY2guUklER0VfTEFTU09bal1bWzFdXVtpXSAlPiUgDQogICAgICAgIHNldF9uYW1lcyhubSA9IGJlc3QuaW5kLm5vbi5zZWFyY2guUklER0VfTEFTU09bal1bWzFdXVtbaV1dWyJtb2RlbCJdKQ0KICAgICAgfSANCikNCiAgICAgIH0NCiAgICAgICApDQogIA0KDQoNCmBgYA0KDQoNCiMgQ3JlYXRlIGFsbCBSZXNwb25zZSBDdXJ2ZXMgLSBSTE0NCg0KYGBge3IsIHdhcm5pbmcgPSBGQUxTRX0NCg0KDQpzdGFydF90aW1lIDwtIFN5cy50aW1lKCkNCg0KZml0cy5ub24uc2VhcmNoLlJMTSA8LSBsYXBwbHkoDQogIDE6bGVuZ3RoKGRmX25hbWVzKSwNCiAgZnVuY3Rpb24oaSkgew0KICAgIG1vZGVsX3dyYXBwZXJfZnVuY3Rpb24yKGRmID0gZGZfbmFtZXNbaV1bWzFdXSkNCiAgfQ0KKQ0KDQplbmRfdGltZSA8LSBTeXMudGltZSgpDQoNCmNvbWJpbmVkX3JsbV90aW1lIDwtIHN0YXJ0X3RpbWUgLSBlbmRfdGltZQ0KDQpiZXN0LmluZC5ub24uc2VhcmNoLlJMTSA8LSBsYXBwbHkoDQogIDE6bGVuZ3RoKGRmX25hbWVzKSwNCiAgZnVuY3Rpb24oaSkgeyAgIA0KICBsYXBwbHkoMTpsZW5ndGgoZGZfbmFtZXNbaV1bWzFdXSksIGJlc3RfaW5kX2Z1bmN0aW9uLGRmID0gZml0cy5ub24uc2VhcmNoLlJMTVtpXVtbMV1dLA0KICAgICAgICAgZGYyID0gZGZfbmFtZXNbaV1bWzFdXSkNCiAgfQ0KKQ0KDQpjb2VmLm5vbi5zZWFyY2guUkxNIDwtIGxhcHBseSgNCiAgMTpsZW5ndGgoZGZfbmFtZXMpLA0KICBmdW5jdGlvbiAoaSl7DQogIGJlc3QuaW5kLm5vbi5zZWFyY2guUkxNW2ldW1sxXV0gJT4lIGJpbmRfcm93cw0KICB9DQopICU+JQ0KICBiaW5kX3Jvd3MoKSAlPiUgDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogIG11dGF0ZSgNCiAgICBjb3N0X3AyID0gMCwNCiAgICBsYW1iZGEgPSAwLA0KICAgIGFscGhhID0gMCwNCiAgICBwb3dlcnMyID0gMA0KICApICU+JSANCiAgc2VsZWN0KG9uZV9vZihjb2xuYW1lcyhjb2VmLjJfbWF0cml4KSkpDQoNCg0KYmVzdC5maXQubm9uLnNlYXJjaC5STE0gPC0gbGFwcGx5KDE6bGVuZ3RoKGRmX25hbWVzKSwNCiAgICAgIGZ1bmN0aW9uKGopIHsNCmxhcHBseSgxOmxlbmd0aChiZXN0LmluZC5ub24uc2VhcmNoLlJMTVtbal1dKSwNCiAgICAgIGZ1bmN0aW9uKGkpew0KICAgICAgICBiZXN0LmluZC5ub24uc2VhcmNoLlJMTVtqXVtbMV1dW2ldICU+JSANCiAgICAgICAgc2V0X25hbWVzKG5tID0gYmVzdC5pbmQubm9uLnNlYXJjaC5STE1bal1bWzFdXVtbaV1dWyJtb2RlbCJdKQ0KICAgICAgfSANCikNCiAgICAgIH0NCiAgICAgICApDQoNCg0KICANCmBgYA0KDQoNCmBgYHtyfQ0KDQotY29tYmluZWRfcmlkZ2VfdGltZStjb21iaW5lZF9ybG1fdGltZQ0KDQpgYGANCg0KDQpgYGB7ciwgd2FybmluZyA9IEZBTFNFfQ0KDQpncmFwaC5saXN0LnJsbSA8LSBsYXBwbHkoMTpsZW5ndGgoZGZfbmFtZXMpLA0KICAgICAgZnVuY3Rpb24oaSl7DQogICAgICBsYXBwbHkoMTpsZW5ndGgoYmVzdC5maXQubm9uLnNlYXJjaC5STE1baV1bWzFdXSksIGdyYXBoaW5nX2Z1bmN0aW9uX3JsbSwgZGYxPSBiZXN0LmZpdC5ub24uc2VhcmNoLlJMTVtpXSxkZjIgPSBkZl9uYW1lc1tpXSkNCiAgICAgIH0gDQopDQoNCg0KZ3JhcGgubGlzdC5SSURHRV9MQVNTTyA8LSBsYXBwbHkoMTpsZW5ndGgoZGZfbmFtZXMpLA0KICAgICAgZnVuY3Rpb24oaSl7DQogICAgICBsYXBwbHkoMTpsZW5ndGgoYmVzdC5maXQubm9uLnNlYXJjaC5SSURHRV9MQVNTT1tpXVtbMV1dKSwgZ3JhcGhpbmdfZnVuY3Rpb25fZWxhc3RpY25ldCwgZGYxPSBiZXN0LmZpdC5ub24uc2VhcmNoLlJJREdFX0xBU1NPW2ldLGRmMiA9IGRmX25hbWVzW2ldKQ0KICAgICAgfSANCikNCg0KDQoNCg0KYGBgDQoNCg0KIyMjIEV4cG9ydCBhbGwgUGxvdHMNCg0KYGBge3J9DQoNCmZvbGRlcl9uYW1lMSA8LSBwYXN0ZTAoIk91dHB1dC8iLCAib3V0cHV0ZmlsZXNfIiwgU3lzLkRhdGUoKSwgIl8iLCAiUkxNIiwgIi8iKQ0KZGlyLmNyZWF0ZShmb2xkZXJfbmFtZTEpICMgaXQgd2lsbCB0aHJvdyBhIHdhcm5pbmcgaWYgZm9sZGVyIGV4aXN0cw0KDQpsYXBwbHkoMTpsZW5ndGgoZGZfbmFtZXMpLA0KICAgICAgZnVuY3Rpb24oaikgew0KbGFwcGx5KDE6bGVuZ3RoKGRmX25hbWVzW1tqXV0pLGV4cG9ydF9ycGxvdHNfZnVuY3Rpb24yLHN0YXJ0aW5nX25hbWUgPSAiTm9uX1NlYXJjaF8iLGZvbGRlcl9uYW1lID0gZm9sZGVyX25hbWUxLGRmX2xpc3QgPSBkZl9uYW1lc1tbal1dLGdyYXBoaW5nX2xpc3QgPSBncmFwaC5saXN0LnJsbVtqXVtbMV1dKQ0KICAgICAgfQ0KICAgICAgICkNCg0KZm9sZGVyX25hbWUyIDwtIHBhc3RlMCgiT3V0cHV0LyIsICJvdXRwdXRmaWxlc18iLCBTeXMuRGF0ZSgpLCAiXyIsICJFbGFzdGljTmV0IiwgIi8iKQ0KZGlyLmNyZWF0ZShmb2xkZXJfbmFtZTIpICMgaXQgd2lsbCB0aHJvdyBhIHdhcm5pbmcgaWYgZm9sZGVyIGV4aXN0cw0KDQoNCmxhcHBseSgxOmxlbmd0aChkZl9uYW1lcyksDQogICAgICBmdW5jdGlvbihqKSB7DQpsYXBwbHkoMTpsZW5ndGgoZGZfbmFtZXNbW2pdXSksZXhwb3J0X3JwbG90c19mdW5jdGlvbjIsc3RhcnRpbmdfbmFtZSA9ICJOb25fU2VhcmNoXyIsZm9sZGVyX25hbWUgPSBmb2xkZXJfbmFtZTIsZGZfbGlzdCA9IGRmX25hbWVzW1tqXV0sZ3JhcGhpbmdfbGlzdCA9IGdyYXBoLmxpc3QuUklER0VfTEFTU09bal1bWzFdXSkNCiAgICAgIH0NCiAgICAgICApDQoNCmBgYA0KDQojIyMgU2hvdyBHcmFwaHMNCg0KYGBge3J9DQpsYXBwbHkoMTpsZW5ndGgoZGZfbmFtZXMpLA0KZnVuY3Rpb24oail7DQogIHN1YnBsb3QoZ3JhcGgubGlzdC5ybG1bal1bWzFdXSwgbnJvd3MgPSBsZW5ndGgoZ3JhcGgubGlzdC5ybG1bal1bWzFdXSkpDQp9DQopDQoNCg0KbGFwcGx5KDE6bGVuZ3RoKGRmX25hbWVzKSwNCmZ1bmN0aW9uKGkpew0KI3AxID0gZ3JhcGhfbmFtZXNbaV1bWzFdXQ0KZG8uY2FsbChncmlkLmFycmFuZ2UsZ3JhcGgubGlzdC5ybG1baV1bWzFdXSkNCiNyZXR1cm4oZ3JpZC5hcnJhbmdlKGdyb2JzID0gcDEpKQ0KfQ0KKQ0KDQoNCg0KYGBgDQoNCmBgYHtyfQ0KbGFwcGx5KDE6bGVuZ3RoKGRmX25hbWVzKSwNCmZ1bmN0aW9uKGopew0KICBzdWJwbG90KGdyYXBoLmxpc3QuUklER0VfTEFTU09bal1bWzFdXSwgbnJvd3MgPSBsZW5ndGgoZ3JhcGgubGlzdC5SSURHRV9MQVNTT1tqXVtbMV1dKSkNCn0NCikNCg0KDQpsYXBwbHkoMTpsZW5ndGgoZGZfbmFtZXMpLA0KZnVuY3Rpb24oaSl7DQojcDEgPSBncmFwaF9uYW1lc1tpXVtbMV1dDQpkby5jYWxsKGdyaWQuYXJyYW5nZSxncmFwaC5saXN0LlJJREdFX0xBU1NPW2ldW1sxXV0pDQojcmV0dXJuKGdyaWQuYXJyYW5nZShncm9icyA9IHAxKSkNCn0NCikNCg0KYGBgDQoNCg0KIyBUZXN0aW5nIE1ldGFmb3IgUGFja2FnZQ0KDQpgYGB7cn0NCg0KcF9sb2FkKGxtZTQpDQpwX2xvYWQobWV0YWZvcmVzdCkNCg0KYGBgDQoNCiMjIFRlc3Rpbmcgb24gRFNNIERhdGENCg0KIyMjIExvYWQgaW4gRGF0YQ0KYGBge3J9DQoNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX3ByZSA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZSAlPiUNCiAgZmlsdGVyKHBhID09ICJEU00iKSAlPiUNCiAgZmlsdGVyKHJlZ2lvbl92MiAhPSAiQVBBQyIpICU+JQ0KICAjIGZpbHRlcihhYnNvbHV0ZV9saWZ0IDwgMTAwMCkgIyAlPiUNCiAgIyBmaWx0ZXIoc3R1ZHlfaWQgIT0gJzYyOTc0MjAnKSAjJT4lDQogICMgIGZpbHRlcihzdHVkeV9pZCAhPScxNDkxNjE3MTEnKSAlPiUNCiAgIyAgZmlsdGVyKHN0dWR5X2lkICE9ICcxNDg2MTMwMDInKSAlPiUNCiAgIyBmaWx0ZXIoc3R1ZHlfaWQgIT0nMzI4NDYyNScpICU+JQ0KICAjICBmaWx0ZXIoc3R1ZHlfaWQgIT0nMzMyOTEzMScpDQogIG11dGF0ZSgNCiAgICBpZDIgPSByb3dfbnVtYmVyKCkNCiAgKQ0KDQpkZl90ZXN0IDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbV9wcmUgJT4lDQogICMgc2VsZWN0KC1zdHVkeV9pZCwgLWlkMiwgLXJlZ2lvbiwgLXNjYWxpbmdfZmFjdG9yLCAtcXVhcnRlciwgLXBhLCAtc3R1ZHlfbmFtZSkNCiAgc2VsZWN0KA0KICAgIHJlZ2lvbl92MiwgY291bnRyeSwgY2hhbm5lbCwgdGFjdGljLA0KICAgICMgdHJlYXRtZW50X3VzZXJfY291bnQ6Y29udHJvbCwNCiAgICBjb3N0X3NwZW50X29uX2V4cG9zZWRfZ3JvdXA6YWJzb2x1dGVfbGlmdA0KICApDQoNCmlzb19kc20gPC0gaXNvbGF0aW9uRm9yZXN0JG5ldyhzYW1wbGVfc2l6ZSA9IG5yb3coZGZfdGVzdCksIG51bV90cmVlcyA9IDEwMDAwLCBzZWVkID0gMTE1MikNCg0KaXNvX2RzbSRmaXQoZGZfdGVzdCkNCg0Kc2NvcmVzX3RyYWluIDwtIGRmX3Rlc3QgJT4lDQogIGlzb19kc20kcHJlZGljdCgpICU+JQ0KICBhcnJhbmdlKGRlc2MoYW5vbWFseV9zY29yZSkpDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbV9NZXRhNF9WMSA8LQ0KICBGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9kc21fcHJlICU+JQ0KICBsZWZ0X2pvaW4oc2NvcmVzX3RyYWluLCBieSA9IGMoImlkMiIgPSAiaWQiKSkgJT4lDQogZmlsdGVyKGF2ZXJhZ2VfZGVwdGggPiA1LjEpDQoNCg0KRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX01ldGE0IDwtDQogIEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbV9NZXRhNF9WMSAlPiUNCiAgbmFtZWRfZ3JvdXBfc3BsaXQocmVnaW9uX3YyKQ0KDQpgYGANCg0KIyMjIFN0YW5kYXJkaXplIERhdGENCg0KYGBge3J9DQpGaW5hbF9DTFNfMjAyMl9TdHVkeV9MaXN0X05vbl9TZWFyY2hfbW9kZWxfZmlsZV9kc21fTWV0YTRfVjEgJT4lIA0KICBtdXRhdGUoDQogICAgDQogICkNCmBgYA0KDQoNCiMjIyBSdW4gYSBGaXhlZC1FZmZlY3RzIE1vZGVsDQpbRG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly9janZhbmxpc3NhLmdpdGh1Yi5pby9Eb2luZy1NZXRhLUFuYWx5c2lzLWluLVIvZml4ZWRlZi5odG1sKQ0KYGBge3IsIGZpZy5oZWlnaHQ9IDE1fQ0KDQoNCiNkZl9zbWQgDQoNCg0KaSA9IDENCg0KeWlfRFNNID0gRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX01ldGE0W1tpXV1bJ2Fic29sdXRlX2xpZnQnXSAlPiUgdW5saXN0KCkNCnZpX0RTTSA9IEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbV9NZXRhNFtbaV1dWydTaWduaWZpY2FudF9TcGVuZCddXjEgJT4lIHVubGlzdCgpDQpzcGxpdDIgPSBmYWN0b3IoRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX01ldGE0W1tpXV1bJ2NoYW5uZWwnXSAlPiUgdW5saXN0KCksbGFiZWxzID0gdW5pcXVlKEZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbV9NZXRhNFtbaV1dWydjaGFubmVsJ10pICU+JSB1bmxpc3QoKSkNCg0KDQptX3JlZyA8LSBybWEoeWkgPSB5aV9EU00sICAgICAjIFRoZSBkLWNvbHVtbiBvZiB0aGUgZGYsIHdoaWNoIGNvbnRhaW5zIENvaGVuJ3MgZA0KICAgICAgICAgdmkgPSB2aV9EU00gICAjIFRoZSB2aS1jb2x1bW4gb2YgdGhlIGRmLCB3aGljaCBjb250YWlucyB0aGUgdmFyaWFuY2VzDQogICAgICAgICAsbW9kcyA9IH5zcGxpdDItMSAjdG8gcmVtb3ZlIGludGVyY2VwdCBiZXR3ZWVuIHNsb3Blcw0KICAgICAgICAgKSAgDQogICAgICAgDQoNCm1vZDFfdGVzdA0KDQojcm0oRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX01ldGE0X1YxKSMsbW9kMV90ZXN0LCBpKQ0KDQpwcmVkaWN0KG1vZDFfdGVzdCkNCg0KDQpmb3Jlc3QobW9kMV90ZXN0LCBzbGFiID0gRmluYWxfQ0xTXzIwMjJfU3R1ZHlfTGlzdF9Ob25fU2VhcmNoX21vZGVsX2ZpbGVfZHNtX01ldGE0W1tpXV1bJ3N0dWR5X25hbWUnXSAlPiUgdW5saXN0KCksIGFkZGNyZWQgPSBUUlVFKQ0KYGBgDQojIyMgQWRkaXRpb25hbCBUZXN0DQoNCmBgYHtyfQ0KDQojIFNwZWNpZnkgYmFzaWMgcGxvdCwgbWFwcGluZyBzZXggdG8gdGhlIHgtYXhpcywgZWZmZWN0IHNpemUgJ2QnIHRvIHRoZSB5LWF4aXMsDQojIGFuZCAnd2VpZ2h0cycgdG8gdGhlIHdlaWdodCBwYXJhbWV0ZXIuDQoNCkZpbmFsX0NMU18yMDIyX1N0dWR5X0xpc3RfTm9uX1NlYXJjaF9tb2RlbF9maWxlX2RzbV9NZXRhNFtbaV1dICU+JSANCiAgZ2dwbG90KCkrDQogIGFlcygNCiAgICB4ID0gY29zdF9zcGVudF9vbl9leHBvc2VkX2dyb3VwLA0KICAgIHkgPSBhYnNvbHV0ZV9saWZ0LA0KICAgIHNpemUgPSAxL3NxcnQoY29zdF9zcGVudF9vbl9leHBvc2VkX2dyb3VwKQ0KICApICsNCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEpICsgIyBBZGQgc2NhdHRlcg0KICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSBtX3JlZyRiWzFdLCBzbG9wZSA9IG1fcmVnJGJbM10pICsgIyBBZGQgcmVncmVzc2lvbiBsaW5lDQogIHRoZW1lX2J3KCkgKyAjIEFwcGx5IGJsYWNrIGFuZCB3aGl0ZSB0aGVtZQ0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICMgUmVtb3ZlIGxlZ2VuZA0KDQpgYGANCg0KYGBge3J9DQoNCmBgYA0KDQo=